using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace DrugiProjekt
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Prostopadloscian_Efekt : Microsoft.Xna.Framework.DrawableGameComponent
    {
        VertexBuffer buforWerteksow;
        GraphicsDevice gd;
        Effect efekt;
        Matrix World, ViewProjection;

        /*
        public Texture2D Tekstura
        {
            set
            {
                efekt.Texture = value;
            }
            get
            {
                return efekt.Texture;
            }
        }

        public Boolean TeksturowanieWlaczone
        {
            set
            {
                efekt.TextureEnabled = value;
            }
            get
            {
                return efekt.TextureEnabled;
            }
        }
        */

        public Prostopadloscian_Efekt(Game game, Effect efekt, Matrix World, Matrix View, Matrix Projection, float dx, float dy, float dz, Color? kolor = null)
            : base(game)
        {
            gd = game.GraphicsDevice;
            this.efekt = efekt.Clone();
            this.World = World;
            this.ViewProjection = View * Projection;

            dx /= 2;
            dy /= 2;
            dz /= 2;

            Vector3[] punkty = new Vector3[8]
            {
                new Vector3(-dx,-dy,dz),
                new Vector3(dx,-dy,dz),
                new Vector3(dx,dy,dz),
                new Vector3(-dx,dy,dz),

                new Vector3(-dx,-dy,-dz),
                new Vector3(dx,-dy,-dz),
                new Vector3(dx,dy,-dz),
                new Vector3(-dx,dy,-dz)
            };

            Color kolor1,kolor2,kolor3;
            if (kolor == null)
            {
                kolor1 = Color.Cyan;
                kolor2 = Color.Magenta;
                kolor3 = Color.Yellow;
            }
            else
            {
                kolor1 = kolor.Value;
                kolor2 = kolor.Value;
                kolor3 = kolor.Value;
            }

            Vector2 t00 = new Vector2(0, 0);
            Vector2 t01 = new Vector2(0, 1);
            Vector2 t10 = new Vector2(1, 0);
            Vector2 t11 = new Vector2(1, 1);
            
            VertexPositionColorNormalTexture[] werteksy = new VertexPositionColorNormalTexture[6*4]
            {
                //przednia sciana
                new VertexPositionColorNormalTexture(punkty[3], kolor1, Vector3.UnitZ, t00),
                new VertexPositionColorNormalTexture(punkty[2], kolor1, Vector3.UnitZ, t10),
                new VertexPositionColorNormalTexture(punkty[0], kolor1, Vector3.UnitZ, t01),
                //new VertexPositionColorNormalTexture(punkty[0], kolor1),
                //new VertexPositionColorNormalTexture(punkty[2], kolor1),
                new VertexPositionColorNormalTexture(punkty[1], kolor1, Vector3.UnitZ, t11),

                //tylnia sciana
                new VertexPositionColorNormalTexture(punkty[7], kolor1, -Vector3.UnitZ, t10),
                new VertexPositionColorNormalTexture(punkty[4], kolor1, -Vector3.UnitZ, t11),
                new VertexPositionColorNormalTexture(punkty[6], kolor1, -Vector3.UnitZ, t00),
                //new VertexPositionColorNormalTexture(punkty[6], kolor1),
                //new VertexPositionColorNormalTexture(punkty[4], kolor1),
                new VertexPositionColorNormalTexture(punkty[5], kolor1, -Vector3.UnitZ, t01),

                //gorna sciana
                new VertexPositionColorNormalTexture(punkty[3], kolor2, Vector3.UnitY, t00),
                new VertexPositionColorNormalTexture(punkty[7], kolor2, Vector3.UnitY, t10),
                new VertexPositionColorNormalTexture(punkty[2], kolor2, Vector3.UnitY, t01),
                //new VertexPositionColorNormalTexture(punkty[2], kolor2),
                //new VertexPositionColorNormalTexture(punkty[7], kolor2),
                new VertexPositionColorNormalTexture(punkty[6], kolor2, Vector3.UnitY, t11),

                //dolna sciana
                new VertexPositionColorNormalTexture(punkty[0], kolor2, -Vector3.UnitY, t00),
                new VertexPositionColorNormalTexture(punkty[1], kolor2, -Vector3.UnitY, t10),
                new VertexPositionColorNormalTexture(punkty[4], kolor2, -Vector3.UnitY, t01),
                //new VertexPositionColorNormalTexture(punkty[4], kolor2),
                //new VertexPositionColorNormalTexture(punkty[1], kolor2),
                new VertexPositionColorNormalTexture(punkty[5], kolor2, -Vector3.UnitY, t11),

                //lewa sciana
                new VertexPositionColorNormalTexture(punkty[3], kolor3, -Vector3.UnitX, t10),
                new VertexPositionColorNormalTexture(punkty[0], kolor3, -Vector3.UnitX, t11),
                new VertexPositionColorNormalTexture(punkty[7], kolor3, -Vector3.UnitX, t00),
                //new VertexPositionColorNormalTexture(punkty[7], kolor3),
                //new VertexPositionColorNormalTexture(punkty[0], kolor3),
                new VertexPositionColorNormalTexture(punkty[4], kolor3, -Vector3.UnitX, t01),

                //prawa sciana
                new VertexPositionColorNormalTexture(punkty[1], kolor3, Vector3.UnitX, t01),
                new VertexPositionColorNormalTexture(punkty[2], kolor3, Vector3.UnitX, t00),
                new VertexPositionColorNormalTexture(punkty[5], kolor3, Vector3.UnitX, t11),
                //new VertexPositionColorNormalTexture(punkty[5], kolor3),
                //new VertexPositionColorNormalTexture(punkty[2], kolor3),
                new VertexPositionColorNormalTexture(punkty[6], kolor3, Vector3.UnitX, t10)
            };

            buforWerteksow = new VertexBuffer(gd, VertexPositionColorNormalTexture.VertexDeclaration, werteksy.Length, BufferUsage.WriteOnly);
            buforWerteksow.SetData<VertexPositionColorNormalTexture>(werteksy);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            //efekt.World *= Matrix.CreateRotationY(0.02f) * Matrix.CreateRotationX(0.01f);

            KeyboardState klawiatura = Keyboard.GetState();

            Matrix macierzObrotow = Matrix.Identity;
            float kat = 0.01f;
            if (klawiatura.IsKeyDown(Keys.LeftControl)) kat *= 3;
            if (klawiatura.IsKeyDown(Keys.Up)) macierzObrotow *= Matrix.CreateRotationX(-kat);
            if (klawiatura.IsKeyDown(Keys.Down)) macierzObrotow *= Matrix.CreateRotationX(kat);
            if (klawiatura.IsKeyDown(Keys.Left)) macierzObrotow *= Matrix.CreateRotationY(-kat);
            if (klawiatura.IsKeyDown(Keys.Right)) macierzObrotow *= Matrix.CreateRotationY(kat);

            World*=macierzObrotow;
            efekt.Parameters["WorldViewProjection"].SetValue(World * ViewProjection);

            efekt.Parameters["Czas"].SetValue((float)gameTime.TotalGameTime.TotalSeconds);

            base.Update(gameTime);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Draw(GameTime gameTime)
        {
            gd.SetVertexBuffer(buforWerteksow);

            foreach (EffectPass pass in efekt.CurrentTechnique.Passes)
            {
                pass.Apply();

                //gd.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
                for (int i = 0; i < 6; ++i)
                {
                    gd.DrawPrimitives(PrimitiveType.TriangleStrip, 4*i, 2);
                }
            }

            base.Draw(gameTime);
        }
    }
}
