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

namespace Log740
{
    class AbstractPlaneExemple : AbstractExemple
    {
        protected Vecteur3F direction;
        protected Vecteur3F cotangent;
        protected double speed_forward;
        protected double speed_turn;
        protected double speed_pitch;
        private double _roll;
        private double _turn;
        private double _pitch;

        private const double MIN_PITCH = -Math.PI / 4;
        private const double MAX_PITCH = Math.PI / 4;
        private const double MIN_ROLL = 3 * -Math.PI / 8;
        private const double MAX_ROLL = 3 * Math.PI / 8;

        public AbstractPlaneExemple() : base(30)
        {
            updateOrientation();
            ResetPosition();
        }

        protected double roll
        {
            get
            {
                return this._roll;
            }
            set
            {
                this._roll = value;
                this._roll = Math.Min(MAX_ROLL, this._roll);
                this._roll = Math.Max(MIN_ROLL, this._roll);
            }
        }

        protected override void ResetPosition()
        {
            base.ResetPosition();
            position.Z = 1;

            speed_pitch = 0;
            speed_forward = 0.5;
            speed_turn = 0;

            _roll = 0;
            _turn = 0;
            _pitch = 0;

            updateOrientation();
        }

        private void updateOrientation()
        {
            Quaternion qroll = Quaternion.FromAxisAngle(0, 0, 1, _roll);
            Quaternion qpitch = Quaternion.FromAxisAngle(1, 0, 0, _pitch - Math.PI / 2);
            Quaternion qturn = Quaternion.FromAxisAngle(0, 0, 1, _turn);

            CameraRotation = qroll * qpitch * qturn;

            Quaternion qcam = CameraRotation.Inverted();

            direction = qcam * new Vecteur3F(0, 0, -1);
            cotangent = qcam * new Vecteur3F(1, 0, 0);
        }

        override protected void AnimateScene()
        {
            base.AnimateScene();

            CameraPosition = position;
            position += speed_forward * direction;

            if (position.Z < 1)
            {
                position.Z = 1;
            }

            _turn += speed_turn;
            _pitch += speed_pitch;

            _pitch = Math.Min(MAX_PITCH, _pitch);
            _pitch = Math.Max(MIN_PITCH, _pitch);

            updateOrientation();
        }

        protected override bool DrawGLScene()
        {
            Vecteur3F cotangent_rolled = CameraRotation.Inverted() * Quaternion.FromAxisAngle(0, 0, 1, -_roll / 2) * new Vecteur3F(1, 0, 0);
            Vecteur3F offset = position + 3 * direction;
            Vecteur3F down = direction.Cross(cotangent_rolled);
            Vecteur3F p1 = offset + direction + 0.5 * down;
            Vecteur3F p2 = offset + 0.5 * down;
            Vecteur3F p3 = offset + cotangent_rolled + down;
            Vecteur3F p4 = offset - cotangent_rolled + down;
            Vecteur3F p5 = p3 - speed_forward * direction;
            Vecteur3F p6 = p4 - speed_forward * direction;
            Gl.glColor3f(1, 1, 0);
            Gl.glBegin(Gl.GL_TRIANGLES);
            Gl.glVertex3d(p1.X, p1.Y, p1.Z);
            Gl.glVertex3d(p2.X, p2.Y, p2.Z);
            Gl.glVertex3d(p3.X, p3.Y, p3.Z);

            Gl.glVertex3d(p1.X, p1.Y, p1.Z);
            Gl.glVertex3d(p4.X, p4.Y, p4.Z);
            Gl.glVertex3d(p2.X, p2.Y, p2.Z);
            Gl.glEnd();

            Gl.glLineWidth(5);
            Gl.glColor3f(1, 0.5f, 0);
            Gl.glBegin(Gl.GL_LINES);
            Gl.glVertex3d(p3.X, p3.Y, p3.Z);
            Gl.glVertex3d(p5.X, p5.Y, p5.Z);

            Gl.glVertex3d(p4.X, p4.Y, p4.Z);
            Gl.glVertex3d(p6.X, p6.Y, p6.Z);
            Gl.glEnd();
            Gl.glLineWidth(1);
            return base.DrawGLScene();
        }
    }
}
