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

namespace Obligatorisk
{
    class Car : 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 Gears gear;
        private float yawIncrement;
        private float maxYawIncrement;
        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 Gears Gear
        {
            get { return this.gear; }
            set { this.gear = value; }
        }
        public Car(Model aModel, Device aDevice, Vector3 aPosition)
            : base(aPosition)
        {
            theDevice = aDevice;
            theModel = aModel;
            CreateMesh();
            Yaw = 0.000000f;//(float)(2F * Math.PI / 360F) * 500;
            Pitch = 4.7f;//(float)(2F * Math.PI / 360F) * 10F;
            kameraPosition = 1;
            Distance = 5;
            this.gear = Gears.Neutral;
            this.maxYawIncrement = 0.040f;
        }
        public enum Gears
        {
            Reverse,
            Neutral,
            First,
            Second,
            Third,
            Fourth,
            Fifth,
            Sixth,
        }
        public void CreateMesh()
        {
            ExtendedMaterial[] materials = null;
            String path = @"..\..\";
            mesh = Mesh.FromFile(path + @"3D-Models\Audi.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);
            }
        }
        private void PowerCurveRecipe()
        {
            //private float power = 3;
            //turn += PowerCurve(gamepad.ThumbSticks.Left.X) * turnRate;
            //(float)Math.Pow(Math.Abs(value), power) * Math.Sign(value);
        }
        public void Update()
        {
            if (!theModel.PressedKeys.Contains(Keys.Left) && !theModel.PressedKeys.Contains(Keys.Right))
            {
                if (YawIncrement >= 0.000f)
                    YawIncrement -= 0.002f;
                if (YawIncrement <= 0.000f)
                    YawIncrement += 0.002f;
            }
            if (theModel.PressedKeys.Contains(Keys.Right))
            { // Flyet drejer og krænger til højre
                //Formel for centifugalkraft og skridpunkt (dæk og vejoverflade)
                if (Speed > -0.05f && Speed <= 0.05f)
                    YawIncrement = 0;
                if (Speed > 0.05f && Speed <= 5)
                {
                    if (YawIncrement < 0.010f)
                        YawIncrement += 0.0005f;
                    else
                    {
                        YawIncrement = 0.010f;
                        if (YawIncrement < 0.020f)
                            YawIncrement += 0.0005f;
                    }
                }
                if (Speed > 5 && Speed <= 10)
                {
                    if (YawIncrement < 0.020f)
                        YawIncrement += 0.001f;
                    else
                    {
                        YawIncrement = 0.020f;
                        if (YawIncrement < 0.020f)
                            YawIncrement += 0.001f;
                    }
                }
                if (Speed > 10 && Speed <= 20)
                {
                    if (YawIncrement < 0.030f)
                        YawIncrement += 0.002f;
                    else
                    {
                        YawIncrement = 0.030f;
                        if (YawIncrement < 0.030f)
                            YawIncrement += 0.002f;
                    }
                }
                if (Speed > 20 && Speed <= 40)
                {
                    if (YawIncrement < 0.040f)
                        YawIncrement += 0.003f;
                    else
                    {
                        YawIncrement = 0.040f;
                        if (YawIncrement < 0.040f)
                            YawIncrement += 0.003f;
                    }
                }
                if (Speed > 40 && Speed <= 251)
                {
                    if (YawIncrement < 0.040f)
                        YawIncrement += 0.005f;
                    else
                    {
                        YawIncrement = 0.040f;
                        if (YawIncrement < 0.040f)
                            YawIncrement += 0.005f;
                    }
                }
                if (Speed < 0 && Speed >= -251)
                {
                    if (YawIncrement < 0.040f)
                        YawIncrement += 0.005f;
                    else
                    {
                        YawIncrement = 0.040f;
                        if (YawIncrement < 0.040f)
                            YawIncrement += 0.005f;
                    }
                }
                //Roll -= 0.01f;
            }
            if (theModel.PressedKeys.Contains(Keys.Left))
            { // Bilen drejer og krænger til venstre
                //Formel for centifugalkraft og skridpunkt (dæk og vejoverflade)
                if (Speed < 0.05f && Speed >= -0.05f)
                    YawIncrement = 0;
                if (Speed > 0.05f && Speed <= 5)
                {
                    if (YawIncrement > -0.010f)
                        YawIncrement -= 0.0005f;
                    else
                    {
                        YawIncrement = -0.010f;
                        if (YawIncrement > -0.020f)
                            YawIncrement -= 0.0005f;
                    }
                }
                if (Speed > 5 && Speed <= 10)
                {
                    if (YawIncrement > -0.020f)
                        YawIncrement -= 0.001f;
                    else
                    {
                        YawIncrement = -0.020f;
                        if (YawIncrement > -0.020f)
                            YawIncrement -= 0.001f;
                    }
                }
                if (Speed > 10 && Speed <= 20)
                {
                    if (YawIncrement > -0.030f)
                        YawIncrement -= 0.002f;
                    else
                    {
                        YawIncrement = -0.030f;
                        if (YawIncrement > -0.030f)
                            YawIncrement -= 0.002f;
                    }
                }
                if (Speed > 20 && Speed <= 40)
                {
                    if (YawIncrement > -0.040f)
                        YawIncrement -= 0.003f;
                    else
                    {
                        YawIncrement = -0.040f;
                        if (YawIncrement > -0.040f)
                            YawIncrement -= 0.003f;
                    }
                }
                if (Speed > 40 && Speed <= 251)
                {
                    if (YawIncrement > -0.040f)
                        YawIncrement -= 0.005f;
                    else
                    {
                        YawIncrement = -0.040f;
                        if (YawIncrement > -0.040f)
                            YawIncrement -= 0.005f;
                    }
                }
                if (Speed < 0 && Speed >= -251)
                {
                    if (YawIncrement > -0.040f)
                        YawIncrement -= 0.005f;
                    else
                    {
                        YawIncrement = -0.040f;
                        if (YawIncrement > -0.040f)
                            YawIncrement -= 0.005f;
                    }
                }
                //Roll += 0.01f;
            }
            if (theModel.PressedKeys.Contains(Keys.Up))
            { // Mere fart
                //Formel for acceleration
                if (Speed < 30 && Speed > 0)
                    Speed += 1.50F;
                if (Speed < 30)
                    Speed += 1.45F;
                if (Speed < 70)
                    Speed += 1.40F;
                if (Speed < 110)
                    Speed += 1.30F;
                if (Speed < 150)
                    Speed += 1.20F;
                if (Speed < 180)
                    Speed += 1.10F;
                if (Speed < 250)
                    Speed += 0.80F;
                if (Speed < 30 && Speed > 0)
                    this.gear = Gears.First;
                if (Speed < 70 && Speed >= 30)
                    this.gear = Gears.Second;
                if (Speed < 110 && Speed >= 70)
                    this.gear = Gears.Third;
                if (Speed < 150 && Speed >= 110)
                    this.gear = Gears.Fourth;
                if (Speed < 180 && Speed >= 150)
                    this.gear = Gears.Fifth;
                if (Speed < 250 && Speed >= 180)
                    this.gear = Gears.Sixth;
            }
            if (!theModel.PressedKeys.Contains(Keys.Up))
            { // Vind modstand og motorbrems
                if (Speed < 0.000f)
                    Speed -= 0.075F;
                if (Speed < 30 && Speed > 0)
                    this.gear = Gears.First;
                if (Speed < 70 && Speed >= 30)
                    this.gear = Gears.Second;
                if (Speed < 110 && Speed >= 70)
                    this.gear = Gears.Third;
                if (Speed < 150 && Speed >= 110)
                    this.gear = Gears.Fourth;
                if (Speed < 180 && Speed >= 150)
                    this.gear = Gears.Fifth;
                if (Speed < 250 && Speed >= 180)
                    this.gear = Gears.Sixth;
            }
            if (theModel.PressedKeys.Contains(Keys.Down))
            { // Mindre fart
                //Formel for bremselængde, deacceleration
                if (Speed > -100 && Speed <= 250)
                    Speed -= 2.00F;
                if (Speed < 0)
                    this.gear = Gears.Reverse;
                if (Speed == 0)
                    this.gear = Gears.Neutral;
                if (Speed < 30 && Speed > 0)
                    this.gear = Gears.First;
                if (Speed < 70 && Speed >= -30)
                    this.gear = Gears.Second;
                if (Speed < 110 && Speed >= -70)
                    this.gear = Gears.Third;
                if (Speed < 150 && Speed >= -110)
                    this.gear = Gears.Fourth;
                if (Speed < 180 && Speed >= -150)
                    this.gear = Gears.Fifth;
                if (Speed < 250 && Speed >= -180)
                    this.gear = Gears.Sixth;
            }
            if (theModel.PressedKeys.Contains(Keys.Space))
            {
                if (Speed > 10 && Speed < 250)
                    Speed -= 5;
                if (Speed > -250 && Speed < -10)
                    Speed += 5;
                if (Speed < 10 && Speed > 1)
                    Speed = 0;
                if (Speed > -10 && Speed <= 1)
                    Speed = 0;
            }
            if (!theModel.PressedKeys.Contains(Keys.Down))
            { // // Vind modstand og motorbrems
                if (Speed > 0.000f)
                    Speed -= 0.015F;
            }
            if (theModel.PressedKeys.Contains(Keys.K))
            { // Toggle kameraposition
                if (kameraPosition == 1)
                    kameraPosition = 2;
                else if (kameraPosition == 2)
                    kameraPosition = 3;
                else
                    kameraPosition = 1;
            }
            if (theModel.PressedKeys.Contains(Keys.Oemplus))
            {
                this.distance = this.distance + 5.0f;
            }
            if (theModel.PressedKeys.Contains(Keys.OemMinus))
            {
                this.distance = this.distance - 5.0f;
            }
            //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) * 0F, 0));
            Position += v;

            Position = new Vector3(Position.X, 0.001f, Position.Z);
            
            Yaw += YawIncrement;
            Vector3 nyPosition;
            Vector3 nyOp;
            switch (kameraPosition)
            {
                case 1:
                    {
                        theDevice.Transform.View = 
                            Matrix.LookAtLH(new Vector3(0, 10, 50), Position, new Vector3(0, 1, 0));
                        break;
                    }
                case 2:
                    {
                        //* Matrix.Scaling(0.3f, 0.3f, 0.3f) 
                        v = new Vector3(0, 0, 0);
                        v.TransformCoordinate(Matrix.Translation(new Vector3(0, -20, Distance))
                             * Matrix.RotationYawPitchRoll(Yaw, Pitch, 0f));
                        nyPosition = Position + v;
                        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;
                    }
                default:
                    break;
            }
        }
    }
}
