using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VisiMath;
using VisiMath.Geometry;
using VisimBox;
using VisimBox.Renderer;
using VisimBox.Scene;
using VisimBox.Physics;

namespace VisimBuilder.ObjectCreation
{
    public partial class RingCreation : ObjectCreationBasePhysical
    {
        public float Radius;
        public Vector3 Center;
        float Angle, RingWidth, RingHeight;

        public RingCreation() : base()
        {
            InitializeComponent();
            labelObjectName.Text = "Ring Mesh";
            textBoxName.Text = "Ring";
            Angle = 0; RingWidth = 0.5f; RingHeight = 0.5f;
            Radius = 1;
            textBoxAngle.ReadOnly = true;
            radioButton1.Checked = true;
            Center = new Vector3();
            RigidBodyEnabled = false;
        }

        public override void SetDefault()
        {
            base.SetDefault();
            Center = new Vector3();
            Radius = 1;
            this.textBoxSphereCenter.Text = string.Format("{0} : {1} : {2}",
                Center.X.ToString("F"), Center.Y.ToString("F"), Center.Z.ToString("F"));
            this.textBoxSphereRadius.Text = Radius.ToString("F");
            this.trackBar1.Value = 10;
            textBoxName.Text = "Ring";
            Angle = 0; RingWidth = 0.5f; RingHeight = 0.5f;
            this.textBoxSphereRadius.Text = Radius.ToString("F");
            radioButton1.Checked = true;
            textBoxAngle.ReadOnly = true;
        }

        public override Node ObjectCreation(string name, ITransformation itrans, Type VertexType, PhysBodyType physbody, PhysSettingsEdit physsettings, BoundingObjectType bounding, IRenderMaterial mat, Node owner)
        {
            IGeometry boundobject = null;


            int segments = this.trackBar1.Value;

            Ring ring = new Ring(VertexType, Center, Radius, RingHeight, RingWidth, segments, Angle);
          

            if (bounding == BoundingObjectType.BestFit)
            {
                boundobject = GeoFactory.CreateBoundingObject(ring as IndexedGeo);
            }
            else if (bounding == BoundingObjectType.Sphere)
            {
                boundobject = GeoFactory.CreateBoundingSphere(ring as IndexedGeo);
            }
            else if (bounding == BoundingObjectType.Box)
            {
                boundobject = GeoFactory.CreateBoundingBox(ring as IndexedGeo);
            }

            Node rval = null;

            if (DoVisual(physbody))
            {
                //float quality = 0.01f * this.trackBar1.Value;
                GeometryNode gn = new GeometryNode(ring, VertexType, mat);
                gn.CreateMesh();
                gn.BoundingObject = boundobject;
                gn.Trans = itrans;
                gn.Pickable = true;
                owner.AddNode(gn, name);
                owner = gn;
                rval = gn;
            }

            if (DoStatic(physbody))
            {
                StaticCollision sc = new StaticCollision();
                sc.Material = new PhysMaterial(physsettings.DynamicFriction, physsettings.StaticFriction, physsettings.Restitution);
                sc.StaticGeometry = ring;
                sc.GeoType = StaticCollisionType.ExplicitConvex;
                sc.Pickable = !DoVisual(physbody);
                owner.AddNode(sc, "staticcol_" + name);
                if (rval == null)
                    rval = sc;
            }
            return rval;
        }


        public Vector3 ParseString(string str)
        {
            StringParser parser = new StringParser(str, ':');
            if (parser.WordCount != 3)
                return Vector3.Invalid;
            if (!parser.IsFloat(0) || !parser.IsFloat(1) || !parser.IsFloat(2))
                return Vector3.Invalid;

            return new Vector3(parser.GetFloat(0), parser.GetFloat(1), parser.GetFloat(2));
        }

        private void CheckCenter()
        {
            Vector3 vec = ParseString(textBoxSphereCenter.Text);
            if (vec.IsValid())
            {
                Center = vec;
            }
            else
            {
                MessageBox.Show("Invalid vector format!");
                this.textBoxSphereCenter.Text = string.Format("{0} : {1} : {2}",
                    Center.X.ToString("F"), Center.Y.ToString("F"), Center.Z.ToString("F"));
            }
        }

        private void CheckRadius()
        {
            try
            {
                float rad = (float)Convert.ToDouble(textBoxSphereRadius.Text);
                Radius = rad;
            }
            catch
            {
                textBoxSphereRadius.Text = Radius.ToString();
                MessageBox.Show("Invalid radius format!");
            }
        }

        private void CheckWidth()
        {
            try
            {
                float rad = (float)Convert.ToDouble(textBoxWidth.Text);
                RingWidth = rad;
            }
            catch
            {
                textBoxWidth.Text = RingWidth.ToString();
                MessageBox.Show("Invalid size format!");
            }
        }

        private void CheckHeight()
        {
            try
            {
                float rad = (float)Convert.ToDouble(textBoxHeight.Text);
                RingHeight = rad;
            }
            catch
            {
                textBoxHeight.Text = RingHeight.ToString();
                MessageBox.Show("Invalid size format!");
            }
        }


        private void CenterKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                CheckCenter();
            }

        }

        private void CenterFocusLeave(object sender, EventArgs e)
        {
            CheckCenter();
        }

        private void RadiusFocusLeave(object sender, EventArgs e)
        {
            CheckRadius();
        }

        private void HeightFocusLeave(object sender, EventArgs e)
        {
            CheckRadius();
        }
        
        private void WidthFocusLeave(object sender, EventArgs e)
        {
            CheckRadius();
        }

        private void RadiusKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                CheckRadius();
            }
        }
        private void WidthKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                CheckRadius();
            }
        }
        private void HeightKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                CheckRadius();
            }
        }

        private void FullButton(object sender, EventArgs e)
        {
            Angle = MathTools.DoublePi;
            textBoxAngle.ReadOnly = true;
        }

        private void HalfButton(object sender, EventArgs e)
        {
            Angle = MathTools.Pi;
            textBoxAngle.ReadOnly = true;
        }

        private void QuartButton(object sender, EventArgs e)
        {
            Angle = MathTools.QuarterPi;
            textBoxAngle.ReadOnly = true;
        }

        private void UserSizeButton(object sender, EventArgs e)
        {
            textBoxAngle.ReadOnly = false;
            float degrees = MathTools.RadToDeg(Angle, true);
            textBoxAngle.Text = degrees.ToString();
        }


        private void CheckAngle()
        {
            try
            {
                float rad = (float)Convert.ToDouble(textBoxAngle.Text);
                Angle = MathTools.DegToRad(rad);
            }
            catch
            {
                textBoxAngle.Text = MathTools.RadToDeg(Angle, true).ToString();
                MessageBox.Show("Invalid angle format!");
            }            
        }


        private void AngleKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                CheckAngle();
            }
        }

        private void FocusAngle(object sender, EventArgs e)
        {
            CheckAngle();
        }
    }

    public class CreateRingItem : CreateNewItem
    {
        public CreateRingItem(MainBuilderForm boss)
            : base(boss, "Ring", "Ring (or ring part) mesh with settable center, radius, width, thickness and quality")
        {
                        RefreshBaseCreator();
        }

        protected override void RefreshBaseCreator()
        {
            BaseCreator = new RingCreation();
            BaseCreator.Init(Boss);
        }
    }
}
