using System;
using System.Windows.Forms;

namespace Mix.Tool.ModelEditor
{
    /// <summary>
    /// リジッドボディエディターフォームクラス
    /// </summary>
    public partial class ActorRigidBodyEditorForm : Mix.Tool.Docking.DockContent
    {
        private class StatusItem
        {
            private string display = "";
            private Mix.Tool.Dynamics.Design.BasicChildStatus value = Mix.Tool.Dynamics.Design.BasicChildStatus.Default;

            public StatusItem(string _display, Mix.Tool.Dynamics.Design.BasicChildStatus _value)
            {
                this.display = _display;
                this.value = _value;
            }

            public string Display
            {
                get { return this.display; }
            }

            public Mix.Tool.Dynamics.Design.BasicChildStatus Value
            {
                get { return this.value; }
            }
        }

        private Mix.Tool.Dynamics.Design.BasicChild src = null;
        private bool validChangeSrc = true;

        /// <summary>
        /// ソースの取得、または設定
        /// </summary>
        public Mix.Tool.Dynamics.Design.BasicChild Source
        {
            get { return this.src; }
            set
            {
                if (this.src != value)
                {
                    if (this.src != null)
                    {
                        this.src.NameChanged -= new EventHandler(this.src_NameChanged);
                    }

                    this.src = value;

                    if (this.src != null)
                    {
                        //コントロールの初期化を開始
                        this.BeginInitControl();

                        ////////////////////////////////////////////////////////////////////////////////////////////////////

                        Mix.Tool.Dynamics.Design.RotationAxisFlags rotFlags = this.src.RotationAxisFlags;
                        bool colliderEnabled = (this.src.Type == Mix.Tool.Dynamics.Design.BasicChildType.Collider);

                        //イベントの設定
                        this.src.NameChanged += new EventHandler(this.src_NameChanged);

                        //タイトル
                        this.UpdateTitleText();

                        //中心
                        this.nudCPX.Value = Convert.ToDecimal(this.src.CenterPosition.X);
                        this.nudCPY.Value = Convert.ToDecimal(this.src.CenterPosition.Y);
                        this.nudCPZ.Value = Convert.ToDecimal(this.src.CenterPosition.Z);

                        //マテリアル
                        this.cbPhysicsMaterial.Selected = this.src.PhysicsMaterial;

                        if (colliderEnabled == true)
                        {
                            //ステータス
                            this.cbStatus.SelectedValue = this.src.Status;

                            //質量
                            this.nudMass.Value = Convert.ToDecimal(this.src.Mass);

                            //回転
                            this.cbRX.Checked = (rotFlags & Mix.Tool.Dynamics.Design.RotationAxisFlags.X) == Mix.Tool.Dynamics.Design.RotationAxisFlags.X;
                            this.cbRY.Checked = (rotFlags & Mix.Tool.Dynamics.Design.RotationAxisFlags.Y) == Mix.Tool.Dynamics.Design.RotationAxisFlags.Y;
                            this.cbRZ.Checked = (rotFlags & Mix.Tool.Dynamics.Design.RotationAxisFlags.Z) == Mix.Tool.Dynamics.Design.RotationAxisFlags.Z;

                            //常に活動状態
                            this.cbAlwaysActive.Checked = this.src.AlwaysActive;
                        }

                        ////////////////////////////////////////////////////////////////////////////////////////////////////

                        //コントロールの初期化を終了
                        this.EndInitControl();
                    }

                    this.UpdateControlState();
                }
            }
        }

        public ActorRigidBodyEditorForm(Mix.Tool.ModelEditor.Project.Dynamics _dynamics)
        {
            InitializeComponent();

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // コントロールの初期化
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            //コントロールの初期化を開始
            this.BeginInitControl();

            System.Collections.Generic.List<StatusItem> dsStatus = new System.Collections.Generic.List<StatusItem>();

            //ステータスのデータソースを作成
            dsStatus.Add(new StatusItem(Properties.Resources.JP_DEFAULT, Mix.Tool.Dynamics.Design.BasicChildStatus.Default));
            dsStatus.Add(new StatusItem(Properties.Resources.JP_STATIC, Mix.Tool.Dynamics.Design.BasicChildStatus.Static));
            dsStatus.Add(new StatusItem(Properties.Resources.JP_KINEMATIC, Mix.Tool.Dynamics.Design.BasicChildStatus.Kinematic));

            //物理マテリアルのデータソースを設定
            this.cbPhysicsMaterial.DataSource = _dynamics.PhysicsMaterials.DataSource;

            //ステータスのデータソースを設定
            this.cbStatus.DisplayMember = "Display";
            this.cbStatus.ValueMember = "Value";
            this.cbStatus.DataSource = dsStatus;

            //コントロールの初期化を終了
            this.EndInitControl();

            //コントロールの状態を更新
            this.UpdateControlState();
        }

        private void ActorRigidBodyEditorForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.src != null)
            {
                this.src.NameChanged -= new EventHandler(this.src_NameChanged);
            }
        }

        private void src_NameChanged(object sender, EventArgs e)
        {
            this.UpdateTitleText();
        }

        private void nudCPX_ValueChanged(object sender, EventArgs e)
        {
            this.UpdateCenterPosition();
        }

        private void nudCPY_ValueChanged(object sender, EventArgs e)
        {
            this.UpdateCenterPosition();
        }

        private void nudCPZ_ValueChanged(object sender, EventArgs e)
        {
            this.UpdateCenterPosition();
        }

        private void btResetCP_Click(object sender, EventArgs e)
        {
            this.src.ResetCenterPosition();

            this.BeginInitControl();

            this.nudCPX.Value = Convert.ToDecimal(this.src.CenterPosition.X);
            this.nudCPY.Value = Convert.ToDecimal(this.src.CenterPosition.Y);
            this.nudCPZ.Value = Convert.ToDecimal(this.src.CenterPosition.Z);

            this.EndInitControl();
        }

        private void cbPhysicsMaterial_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.AvailableSource == true)
            {
                PhysicsMaterialComboBox cb = sender as PhysicsMaterialComboBox;

                this.src.PhysicsMaterial = cb.Selected;
            }
        }

        private void cbStatus_SelectedValueChanged(object sender, EventArgs e)
        {
            if (this.AvailableSource == true)
            {
                ComboBox cb = sender as ComboBox;

                this.src.Status = (Mix.Tool.Dynamics.Design.BasicChildStatus)cb.SelectedValue;
                this.UpdateControlState();
            }
        }

        private void nudMass_ValueChanged(object sender, EventArgs e)
        {
            if (this.AvailableSource == true)
            {
                this.src.Mass = (float)Convert.ToDouble(this.nudMass.Value);
            }
        }

        private void cbRX_CheckedChanged(object sender, EventArgs e)
        {
            this.UpdateRotationAxisFlags();
        }

        private void cbRY_CheckedChanged(object sender, EventArgs e)
        {
            this.UpdateRotationAxisFlags();
        }

        private void cbRZ_CheckedChanged(object sender, EventArgs e)
        {
            this.UpdateRotationAxisFlags();
        }

        private void cbAlwaysActive_CheckedChanged(object sender, EventArgs e)
        {
            if (this.AvailableSource == true)
            {
                CheckBox cb = sender as CheckBox;
                this.src.AlwaysActive = cb.Checked;
            }
        }

        private void BeginInitControl()
        {
            this.validChangeSrc = false;
        }

        private void EndInitControl()
        {
            this.validChangeSrc = true;
        }

        private bool AvailableSource
        {
            get
            {
                if ((this.validChangeSrc == false) ||
                    (this.src == null))
                {
                    return false;
                }

                return true;
            }
        }

        private void UpdateTitleText()
        {
            if (this.src != null)
            {
                switch (this.src.Type)
                {
                    case Mix.Tool.Dynamics.Design.BasicChildType.Collider:
                        this.Text = string.Format("{0} - {1}({2})", Properties.Resources.JP_RIGID_BODY_EDITOR, Properties.Resources.JP_COLLIDER, this.src.Name);
                        break;
                    case Mix.Tool.Dynamics.Design.BasicChildType.Sensor:
                        this.Text = string.Format("{0} - {1}({2})", Properties.Resources.JP_RIGID_BODY_EDITOR, Properties.Resources.JP_SENSOR, this.src.Name);
                        break;
                    default:
                        this.Text = string.Format("{0} - {1}({2})", Properties.Resources.JP_RIGID_BODY_EDITOR, Properties.Resources.JP_UNKNOWN, this.src.Name);
                        break;
                }
            }
            else
            {
                this.Text = Properties.Resources.JP_RIGID_BODY_EDITOR;
            }
        }

        private void UpdateControlState()
        {
            bool enabled = (this.src != null);
            bool colliderEnabled = ( enabled == true ) && (this.src.Type == Mix.Tool.Dynamics.Design.BasicChildType.Collider);
            bool massObjEnabled = (colliderEnabled == true) && (this.src.Status != Mix.Tool.Dynamics.Design.BasicChildStatus.Static);

            foreach (Control ctrl in this.Controls)
            {
                if ((ctrl == this.lbStatus) ||
                    (ctrl == this.cbStatus) ||
                    (ctrl == this.lbMass) ||
                    (ctrl == this.tlpMass) ||
                    (ctrl == this.lbRotation) ||
                    (ctrl == this.cbRX) ||
                    (ctrl == this.cbRY) ||
                    (ctrl == this.cbRZ) ||
                    (ctrl == this.cbAlwaysActive))
                {
                    //ソースが設定された際に設定しています
                    continue;
                }

                ctrl.Enabled = enabled;
            }

            this.lbStatus.Enabled = colliderEnabled;
            this.cbStatus.Enabled = colliderEnabled;
            this.lbMass.Enabled = massObjEnabled;
            this.tlpMass.Enabled = massObjEnabled;
            this.lbRotation.Enabled = massObjEnabled;
            this.cbRX.Enabled = massObjEnabled;
            this.cbRY.Enabled = massObjEnabled;
            this.cbRZ.Enabled = massObjEnabled;
            this.cbAlwaysActive.Enabled = massObjEnabled;

            if (enabled == true)
            {
                this.Activate();
            }
        }

        private void UpdateCenterPosition()
        {
            if (this.AvailableSource == true)
            {
                Mix.Tool.Math.Vector pos = new Mix.Tool.Math.Vector();

                pos.X = (float)Convert.ToDouble(this.nudCPX.Value);
                pos.Y = (float)Convert.ToDouble(this.nudCPY.Value);
                pos.Z = (float)Convert.ToDouble(this.nudCPZ.Value);

                this.src.CenterPosition = pos;
            }
        }

        private void UpdateRotationAxisFlags()
        {
            if (this.AvailableSource == true)
            {
                Mix.Tool.Dynamics.Design.RotationAxisFlags flags = Mix.Tool.Dynamics.Design.RotationAxisFlags.None;

                if (this.cbRX.Checked == true) { flags |= Mix.Tool.Dynamics.Design.RotationAxisFlags.X; }
                if (this.cbRY.Checked == true) { flags |= Mix.Tool.Dynamics.Design.RotationAxisFlags.Y; }
                if (this.cbRZ.Checked == true) { flags |= Mix.Tool.Dynamics.Design.RotationAxisFlags.Z; }

                this.src.RotationAxisFlags = flags;
            }
        }
    }
}
