using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Tao.OpenGl;

namespace Log740
{
    class Exemple3dx : AbstractExemple
    {
        private TDxInput.Device device;
        private TDxInput.Sensor sensor;
        private TDxInput.Keyboard keyboard;

        private double rotation_x = 0;
        private double rotation_z = 0;
        private double distance = 100;

        private Quaternion quat_3dx = Quaternion.Identity();
        private Quaternion quatz = Quaternion.Identity();
        private Quaternion quatx = Quaternion.FromAxisAngle(1, 0, 0, -Math.PI / 2);

        private const double MIN_X = 0;
        private const double MAX_X = Math.PI / 4;

        private const double MIN_DISTANCE = 50;
        private const double MAX_DISTANCE = 150;

        public Exemple3dx()
            : base(50)
        {
            device = new TDxInput.Device();
            sensor = device.Sensor;
            keyboard = device.Keyboard;

            sensor.SensorInput += new TDxInput._ISensorEvents_SensorInputEventHandler(tdx_SensorInput);
            keyboard.KeyDown += new TDxInput._IKeyboardEvents_KeyDownEventHandler(tdx_KeyDown);

            device.Connect();

            speed_multiplier = 10;

            this.MouseMove += new MouseEventHandler(this.Mouse_Move);
            this.MouseClick += new MouseEventHandler(this.Mouse_Click);

            updateOrientation();
        }

        protected override void Cleanup()
        {
            base.Cleanup();
            device.Disconnect();
        }

        protected override void ResetPosition()
        {
            rotation_x = 0;
            rotation_z = 0;
            distance = 100;
            updateOrientation();
        }

        private void tdx_KeyDown(int keycode)
        {
            if (keycode == 1)
            {
                rotation_x = 0;
                rotation_z = 0;

                quatz = Quaternion.FromAxisAngle(0, 0, 1, rotation_z);
                quat_3dx = Quaternion.FromAxisAngle(1, 0, 0, rotation_x);

                position.X = 0;
                position.Y = 0;
            }
            else if (keycode == 2)
            {
                this.CloseGLWindow();
            }
        }

        private void tdx_SensorInput()
        {
            rotation_x += sensor.Rotation.X / 40;
            rotation_z += sensor.Rotation.Y / 20;

            distance += sensor.Translation.Y / 10;

            distance = Math.Min(MAX_DISTANCE, distance);
            distance = Math.Max(MIN_DISTANCE, distance);

            rotation_x = Math.Min(MAX_X, rotation_x);
            rotation_x = Math.Max(MIN_X, rotation_x);

            updateOrientation();
        }

        private void updateOrientation()
        {
            quatz = Quaternion.FromAxisAngle(0, 0, 1, rotation_z);
            quat_3dx = Quaternion.FromAxisAngle(1, 0, 0, rotation_x);
            position = quatz.Inverted() * quat_3dx.Inverted() * new Vecteur3F(0, -distance, 0);
        }

        override protected void RefreshScene()
        {
            base.RefreshScene(); /* pour Esc -> Close */

            CameraRotation = quatx * quat_3dx * quatz;// *quat_3dx;

            CameraPosition = position;
        }

        private void Mouse_Move(object sender, MouseEventArgs e)
        {
            this.crosshair.Location.X = e.X;
            this.crosshair.Location.Y = this.DisplayRectangle.Height - e.Y;
        }

        private void Mouse_Click(object sender, MouseEventArgs e)
        {
            this.crosshair.Location.X = e.X;
            this.crosshair.Location.Y = this.DisplayRectangle.Height - e.Y;
            if (e.Button == MouseButtons.Left)
            {
                Shoot();
            }
            else if (e.Button == MouseButtons.Right)
            {
                if (selected_enemy != null)
                {
                    selected_enemy.Color = new Vecteur3F(1, 0, 0);
                }

                selected_enemy = SelectedEnemy();

                if (selected_enemy != null)
                {
                    selected_enemy.Color = new Vecteur3F(1, 1, 1);
                }
            }
        }
    }
}
