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

namespace Log740
{
    class AbstractExemple : Viewer
    {
        protected Crosshair crosshair = new Crosshair(new Vecteur3F(1, 1, 1));

        protected Vecteur3F ground_offset = new Vecteur3F(0, 0, 1);
        protected Vecteur3F position = new Vecteur3F(0, 0, 0);

        protected Scene sce = new Scene();

        protected TextGL centre;
        protected TextGL status;

        protected List<Enemy> enemies = new List<Enemy>();
        protected List<Bullet> projectiles = new List<Bullet>();

        protected Cube selected_enemy = null;

        protected bool pointing = false;

        protected double speed_multiplier = 4;

        protected Random rand = new Random();

        public AbstractExemple(int nb_enemies)
        {
            centre = new TextGL(this, "Centre du monde");
            status = new TextGL(this, "");

            // Ajouter les enemis au demarrage
            for (int i = 0; i < nb_enemies; i++)
            {
                Enemy e = new Enemy(rand.NextDouble()); // Vitesse aleatoire
                e.Location = new Vecteur3F(rand.NextDouble() * 100 - 50, rand.NextDouble() * 100 - 50, 3); // Position aleatoire
                e.Size.Z = rand.NextDouble() * 1 + 1; // Taille aleatoire
                
                // Ajouter a la liste d'ennemis et a la scene
                enemies.Add(e);
                sce.AddChildren(e);
            }

            UpdateStatus();
        }

        protected Enemy SelectedEnemy()
        {
            int name = Select(crosshair.Location.X, crosshair.Location.Y, 10, 10);
            ObjectGL selected = sce.Selected(name);

            if (selected is Enemy)
            {
                return (Enemy)selected;
            }
            else
            {
                return null;
            }
        }

        protected void Shoot()
        {
            Vecteur3F speed = speed_multiplier * NormalUnderPixel(crosshair.Location.X, crosshair.Location.Y);
            Bullet b = new Bullet(new Vecteur3F(1, 1, 1), speed, 100);

            b.Location = CameraPosition;

            b.Animate(); // Avancer la balle pour ne pas l'avoir directement dans la camera

            // Ajouter a la liste de projectiles et a la scene
            projectiles.Add(b);
            sce.AddChildren(b);
        }

        virtual protected void ResetPosition()
        {
            position.X = 0;
            position.Y = 0;
        }

        protected void ResetCrosshair()
        {
            // Recentrer la mire
            crosshair.Location = new Vecteur3F(this.DisplayRectangle.Width / 2, this.DisplayRectangle.Height / 2, 0);
        }

        protected void UpdateStatus()
        {
            status.text = String.Format("{0:0} enemies restant", enemies.Count);
        }

        override protected void AnimateScene()
        {
            // Animer la scene
            sce.Animate();

            // Pour chaque balle
            for (int i = 0; i < projectiles.Count; i++)
            {
                Bullet b = projectiles[i];

                foreach (Enemy e in enemies)
                {
                    // Faire un test de collision avec chaque ennemi
                    if (e.Collision(b.Location, b.Speed))
                    {
                        // S'il y a collision, retirer l'ennemi
                        enemies.Remove(e);
                        sce.RemoveChildren(e);
                        UpdateStatus();

                        // et detruire la balle
                        b.Kill();
                        break;
                    }
                }

                // Si la balle est morte (de vieillese ou par collision), la retirer
                if (b.Dead)
                {
                    projectiles.Remove(b);
                    sce.RemoveChildren(b);
                    i--;
                }
            }
        }

        protected override bool DrawGLSceneWithNames()
        {
            sce.DrawWithNames();

            return true;
        }

        override protected bool DrawGLScene()
        {
            Gl.glDisable(Gl.GL_LIGHTING);

            Gl.glColor3f(1, 1, 1);
            centre.Draw();

            Draw2D(status, 100, 100);

            Gl.glEnable(Gl.GL_LIGHTING);

            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 0, 0, 1 });
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { (float)CameraPosition.X, (float)CameraPosition.Y, (float)CameraPosition.Z });

            DrawGround();

            sce.Draw();

            Draw2D(crosshair, 0, 0);

            return true;
        }

        private void DrawGround()
        {
            float Size = 100;
            float Height = -1;
            Gl.glBegin(Gl.GL_QUADS);

            Gl.glColor3d(0, 1, 0);
            Gl.glVertex3f(-Size, -Size, Height);
            Gl.glVertex3f(-Size, Size, Height);
            Gl.glVertex3f(Size, Size, Height);
            Gl.glVertex3f(Size, -Size, Height);

            Gl.glEnd();
        }

        protected override bool InitGL()
        {
            base.InitGL();
            Gl.glEnable(Gl.GL_LIGHT0);                                          
            Gl.glEnable(Gl.GL_LIGHT1);                                          
            Gl.glEnable(Gl.GL_LIGHTING);                                        // Enable Lighting
            Gl.glEnable(Gl.GL_COLOR_MATERIAL);                                  // Enable Material Coloring
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, new float[] { 1, 1, 1, 1 });
            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, new float[] { 0.5f, 0.5f, 0.5f, 1 });

            crosshair.Location = new Vecteur3F(this.DisplayRectangle.Width / 2, this.DisplayRectangle.Height / 2, 0);
            return true;
        }
    }
}
