using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Drawing;

namespace DirectXEksempel07
{
    class Airplane : ModelComponent
    {
        private Mesh mesh;
        private Material[] meshMaterials; // Materials for the mesh
        private Texture[] meshTextures; // Textures for the mesh
        private Device theDevice;
        private Model theModel;
        private float speed;
        private float yawIncrement;
        private int kameraPosition;
        private float distance;

        public float Speed
        {
            get { return speed; }
            set { speed = value; }
        }

        public float YawIncrement
        {
            get { return yawIncrement; }
            set { yawIncrement = value; }
        }

        public float Distance
        {
            get { return distance; }
            set { distance = value; }
        }

        public Airplane(Model aModel, Device aDevice, Vector3 aPosition)
            : base(aPosition)
        {
            theDevice = aDevice;
            theModel = aModel;
            CreateMesh();
            Yaw = (float)(2F * Math.PI / 360F) * 0F;
            Pitch = (float)(2F * Math.PI / 360F) * 10F;
            kameraPosition = 1;
            Distance = -20;
        }

        public void CreateMesh()
        {
            ExtendedMaterial[] materials = null;
            String path = @"..\..\";
            mesh = Mesh.FromFile(path + "triplane.x",
                MeshFlags.SystemMemory, theDevice, out materials);
            if (meshTextures == null)
            {
                // Egenskaber for materialer og texture udtrækkes 
                meshTextures = new Texture[materials.Length];
                meshMaterials = new Material[materials.Length];
                for (int i = 0; i < materials.Length; i++)
                {
                    meshMaterials[i] = materials[i].Material3D;
                    // Set the ambient color for the material (D3DX does not do this)
                    meshMaterials[i].Ambient = meshMaterials[i].Diffuse;
                    meshTextures[i] = TextureLoader.FromFile(theDevice, path + "banana.bmp");
                }
            }
        }

        public void Render()
        {
            // Kamera
            theDevice.RenderState.Lighting = true;
            theDevice.Transform.World = Matrix.RotationYawPitchRoll(Yaw, Pitch, Roll) *
                Matrix.Translation(Position);
            for (int i = 0; i < meshMaterials.Length; i++)
            {
                theDevice.Material = meshMaterials[i];
                theDevice.SetTexture(0, meshTextures[i]);
                mesh.DrawSubset(i);
            }
        }

        public void Update()
        {
            switch (theModel.Keyboard)
            {
                case Keys.Right:
                { // Flyet drejer og krænger til højre
                    YawIncrement += 0.001f;
                    Roll -= 0.01f;
                    break;
                }
                case Keys.Left:
                { // Flyet drejer og krænger til venstre
                    YawIncrement -= 0.001f;
                    Roll += 0.01f;
                    break;
                }
                case Keys.Down:
                { // Styrepind tilbage - flyet hæver næsen
                    Pitch -= 0.01f;
                    break;
                }
                case Keys.Up:
                { // Styrepind tilbage - flyet hæver næsen
                    Pitch += 0.01f;
                    break;
                }
                case Keys.A:
                { // Mere fart
                    Speed += 0.01F;
                    break;
                }
                case Keys.Z:
                { // Mindre fart
                    Speed -= 0.01F;
                    break;
                }
                case Keys.K:
                { // Toggle kameraposition
                    if (kameraPosition == 1)
                        kameraPosition = 2;
                    else if (kameraPosition == 2)
                        kameraPosition = 3;
                    else
                        kameraPosition = 1;
                    break;
                }
                case Keys.Add:
                {
                    Distance =+ 1;
                    break;
                }
                case Keys.Subtract:
                {
                    Distance =- 1;
                    break;
                }
            }
            theModel.Keyboard = Keys.Space;
            // Beregning af næste position
            Vector3 v = new Vector3(0, 0, 0);
            v.TransformCoordinate(Matrix.Translation(new Vector3(0, 0, Speed))
                * Matrix.RotationYawPitchRoll(Yaw, Pitch - (float)(2F * Math.PI / 360F) * 10F, Roll));
            Position += v;
            if (Position.Y < 2f)
            {
                Position = new Vector3(Position.X, 2f, Position.Z);
            }
            Yaw += YawIncrement;
            Vector3 nyPosition;
            Vector3 nyOp;
            switch (kameraPosition)
            {
                case 1:
                    {
                        theDevice.Transform.View =
                            Matrix.LookAtLH(new Vector3(0, 20, -100), Position, new Vector3(0, 1, 0));
                        break;
                    }
                case 2:
                    {
                        v = new Vector3(0, 0, 0);
                        v.TransformCoordinate(Matrix.Translation(new Vector3(0, 0, Distance))
                            * Matrix.RotationYawPitchRoll(Yaw, Pitch, 0f));
                        nyPosition = Position + v;
                        if (nyPosition.Y < 1) nyPosition.Y = 1;
                        theDevice.Transform.View =
                            Matrix.LookAtLH(nyPosition, Position, new Vector3(0, 1, 0));
                        break;
                    }
                case 3:
                    {
                        v = new Vector3(0, 0, 0);
                        v.TransformCoordinate(Matrix.Translation(new Vector3(0, 0, 20f))
                            * Matrix.RotationYawPitchRoll(Yaw, Pitch, Roll));
                        nyPosition = Position + v;
                        nyOp = new Vector3(0, 1, 0);
                        nyOp.TransformCoordinate(Matrix.RotationYawPitchRoll(Yaw, Pitch, Roll));
                        theDevice.Transform.View =
                            Matrix.LookAtLH(Position + new Vector3(0f, 3f, 0f), 
                            nyPosition, nyOp);
                        break;
                    }
            }
        }
    }
}
