using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VisiMath;
using VisimBox;
using VisimBox.Renderer;
using VisimBox.Scene;
using VisiMath.Geometry;

namespace VisimBuilder
{

    enum MoveGizmoSelected
    {
        None = 0, XArrow, YArrow, ZArrow
    };

    class MoveGizmo : Gizmo
    {

        protected IGeometry XArrow;
        protected IGeometry YArrow;
        protected IGeometry ZArrow;

        public float ArrowSize { get; set; }
        public float ArrowLength { get; set; }
        
        public MoveGizmo(MainBuilderForm boss)
            : base(boss)
        {
            ArrowSize = 0.3f;
            ArrowLength = 1.5f;
            MoveSpeed = 1.00f;
            ConstructArrows();
            InLocalCoords = true;
        }


        public virtual void ConstructArrows()
        {
            XArrow = new Pyramid(typeof(NormalVertex), new Vector3(ArrowLength, 0, 0), new Vector3(ArrowLength + ArrowSize, 0, 0), ArrowSize, ArrowSize);
            YArrow = new Pyramid(typeof(NormalVertex), new Vector3(0, ArrowLength, 0), new Vector3(0, ArrowLength + ArrowSize, 0), ArrowSize, ArrowSize);
            ZArrow = new Pyramid(typeof(NormalVertex), new Vector3(0, 0, ArrowLength), new Vector3(0, 0, ArrowLength + ArrowSize), ArrowSize, ArrowSize);
        }


        public override void MyRender(IRenderContext irc)
        {
            float size = ArrowLength;

            //Vector3 xaxis = center, yaxis = center, zaxis = center;
            Vector3 xaxis = new Vector3(size, 0, 0);
            Vector3 yaxis = new Vector3(0, size, 0);
            Vector3 zaxis = new Vector3(0, 0, size);
            Vector3 zero = Vector3.Zero;

            irc.SetTransformation(ref mytrans);


            if ((MoveGizmoSelected)SelectedPart == MoveGizmoSelected.XArrow)
                irc.SetColor(ColorByte.Red);
            else
                irc.SetColor(ColorByte.White);
            irc.RenderGeometry(XArrow);
            irc.DrawLine3D(ref zero, ref xaxis);


            if ((MoveGizmoSelected)SelectedPart == MoveGizmoSelected.YArrow)
                irc.SetColor(ColorByte.Red);
            else
                irc.SetColor(ColorByte.White);
            irc.RenderGeometry(YArrow);
            irc.DrawLine3D(ref zero, ref yaxis);

            if ((MoveGizmoSelected)SelectedPart == MoveGizmoSelected.ZArrow)
                irc.SetColor(ColorByte.Red);
            else
                irc.SetColor(ColorByte.White);
            irc.RenderGeometry(ZArrow);
            irc.DrawLine3D(ref zero, ref zaxis);
            
        }


        public override void MyMove(float dist, Vector3 origo)
        {
            if (Boss.SelectedNode.Trans == null)
                return;

            Vector3 movement;
            switch ((MoveGizmoSelected)SelectedPart)
            {
                case MoveGizmoSelected.XArrow:
                    movement = new Vector3(dist * origo.X, 0, 0);
                    break;
                case MoveGizmoSelected.YArrow:
                    movement = new Vector3(0, dist * origo.Y, 0);
                    break;
                case MoveGizmoSelected.ZArrow:
                    movement = new Vector3(0, 0, dist * origo.Z);
                    break;
                default:
                    return;
            }
            
            VisimBox.Physics.RigidBody rb = Boss.SelectedNode as VisimBox.Physics.RigidBody;
            VisimBox.Physics.StaticCollision sc = Boss.SelectedNode as VisimBox.Physics.StaticCollision;


            if (Boss.Settings.RigidBodyColCheck && rb != null)
            {
                bool movementinvalid = true;
                int maxiterations = 64;
                while (movementinvalid)
                {
                    maxiterations--;
                    if (maxiterations < 0)
                        return;

                    rb.Trans.PushState();
                    if (InLocalCoords)
                        rb.Trans.MoveLocal(ref movement);
                    else rb.Trans.Move(ref movement);

                    //rb.Trans.Position = rb.Trans.Position + movement;

                    if (VisimEngine.Instance.MainScene.CheckPhysicalCollision(rb))
                    {
                        movement.Mul(0.8f);
                        rb.Trans.PopState();
                    }
                    else
                    {
                        rb.Trans.UndoPushState();
                        Boss.SceneChanged = true;
                        return;
                    }
                }
            }
            Boss.SceneChanged = true;
            if (InLocalCoords)
                Boss.SelectedNode.Trans.MoveLocal(ref movement);
            else Boss.SelectedNode.Trans.Move(ref movement);

            if (sc != null)
            {
                if (Boss.Settings.StaticColUpdate)
                {
                    VisimEngine.Instance.MainScene.PhysScene.UpdateStaticCol(sc);
                }
                else Boss.StaticCollisionInvalid = true;
            }

        }

        public override bool MouseHover(Ray ray)
        {
            if (!base.MouseHover(ray))
                return false;

            if (XArrow.Intersects(MyPickingRay))
            {
                SelectedPart = (int)MoveGizmoSelected.XArrow;
                return true;
            }
            if (YArrow.Intersects(MyPickingRay))
            {
                SelectedPart = (int)MoveGizmoSelected.YArrow;
                return true;
            }
            if (ZArrow.Intersects(MyPickingRay))
            {
                SelectedPart = (int)MoveGizmoSelected.ZArrow;
                return true;
            }
            return false;
        }

    }
}
