using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace MojaDrugaGra
{
    class Prostopadloscian : DrawableGameComponent
    {
        private GraphicsDevice gd;
        private BasicEffect efekt;
        private VertexBuffer buforWerteksow;

        public Prostopadloscian(Game game, BasicEffect efekt,
                                float dx, float dy, float dz, Color? kolor) : base(game)
        {
            dx /= 2;
            dy /= 2;
            dz /= 2;
            gd = game.GraphicsDevice;
            this.efekt = (BasicEffect)efekt.Clone();
            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 = kolor ?? Color.Cyan;
            Color kolor2 = kolor ?? Color.Magenta;
            Color kolor3 = kolor ?? Color.Yellow;

            // Vector2 t00 = new Vector2(0, 0);
            // Vector2 t01 = new Vector2(0, 1);
            // Vector2 t10 = new Vector2(1, 0);
            // Vector2 t11 = new Vector2(1, 1);
            //Vector2 t00 = new Vector2(0, 0);
            //Vector2 t01 = new Vector2(0, 4);
            //Vector2 t10 = new Vector2(4, 0);
            //Vector2 t11 = new Vector2(4, 4);

            float f13 = 1f / 3f, f23 = 2f / 3f;

            Vector2 t00 = new Vector2(0, 0);
            Vector2 t01 = new Vector2(0, 1);
            Vector2 t10 = new Vector2(f13, 0);
            Vector2 t11 = new Vector2(f13, 1);
            Vector2 ta00 = new Vector2(f13, 0);
            Vector2 ta01 = new Vector2(f13, 1);
            Vector2 ta10 = new Vector2(f23, 0);
            Vector2 ta11 = new Vector2(f23, 1);
            Vector2 tb00 = new Vector2(f23, 0);
            Vector2 tb01 = new Vector2(f23, 1);
            Vector2 tb10 = new Vector2(1, 0);
            Vector2 tb11 = new Vector2(1, 1);

            VertexPositionColorNormalTexture[] werteksy = new VertexPositionColorNormalTexture[24]
            {
                //przednia sciana
                new VertexPositionColorNormalTexture(punkty[3], kolor1, Vector3.UnitZ, t00),
                new VertexPositionColorNormalTexture(punkty[2], kolor1, Vector3.UnitZ, t01),
                new VertexPositionColorNormalTexture(punkty[0], kolor1, Vector3.UnitZ, t10),
                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[5], kolor1, -Vector3.UnitZ, t01),
                //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[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[4], kolor3, -Vector3.UnitX, t01),
                //prawa sciana
                new VertexPositionColorNormalTexture(punkty[1], kolor3, Vector3.UnitX, tb01),
                new VertexPositionColorNormalTexture(punkty[2], kolor3, Vector3.UnitX, tb00),
                new VertexPositionColorNormalTexture(punkty[5], kolor3, Vector3.UnitX, tb11),
                new VertexPositionColorNormalTexture(punkty[6], kolor3, Vector3.UnitX, tb10),
                //gorna sciana - przeniesiona na koniec
                new VertexPositionColorNormalTexture(punkty[3], kolor2, Vector3.UnitY, ta01),
                new VertexPositionColorNormalTexture(punkty[7], kolor2, Vector3.UnitY, ta00),
                new VertexPositionColorNormalTexture(punkty[2], kolor2, Vector3.UnitY, ta11),
                new VertexPositionColorNormalTexture(punkty[6], kolor2, Vector3.UnitY, ta10)                
            };            

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

            buforWerteksow.SetData<VertexPositionColorNormalTexture>(werteksy);

            /*
            SamplerState ss = new SamplerState();
            ss.AddressU = TextureAddressMode.Mirror;
            ss.AddressV = TextureAddressMode.Mirror;
            gd.SamplerStates[0] = ss;
            */

            gd.RasterizerState = RasterizerState.CullNone;
            gd.BlendState = BlendState.NonPremultiplied;
        }

        public override void Draw(GameTime gameTime)
        {
            gd.SetVertexBuffer(buforWerteksow);
            foreach (EffectPass pass in efekt.CurrentTechnique.Passes)
            {
                pass.Apply();
                for (int i = 0; i < 6; ++i)
                    gd.DrawPrimitives(PrimitiveType.TriangleStrip, 4 * i, 2);
            }
            base.Draw(gameTime);
        }

        public Matrix MacierzSwiata
        {
            get => efekt.World;
            set => efekt.World = value;
        }

        public Matrix MacierzWidoku
        {
            get => efekt.View;
            set => efekt.View = value;            
        }

        public bool TeksturowanieWłączone
        {
            get => efekt.TextureEnabled;
            set => efekt.TextureEnabled = value;
        }

        public Texture2D Tekstura
        {
            get => efekt.Texture;
            set => efekt.Texture = value;
        }
    }
}
