using System;
using System.Drawing;
using System.Numerics;
using SlatedGameToolkit.Framework.Graphics.Textures;

namespace SlatedGameToolkit.Framework.Graphics.Render
{
    public struct RectangleMesh : IMesh
    {
        private Matrix4x4 matRot;
        private bool changed;
        private Vector3 rotation;
        private Vector2 origin, dimensions;
        private ValueTuple<Vector3, Vector2>[] vertices;
        private uint[] indices;

        public ValueTuple<Vector3, Vector2>[] Vertices
        {
            get {
                if (changed) CalculateVertices();
                return vertices;
            }
        }

        public float X {
            get 
            {
                return origin.X;
            }

            set 
            {
                changed = true;
                origin.X = value;
            }
        }

        public float Y {
            get
            {
                return origin.Y;
            }

            set
            {
                changed = true;
                origin.Y = value;
            }
        }

        public float Width
        {
            get
            {
                return dimensions.X;
            }

            set
            {
                changed = true;
                dimensions.X = value;
            }
        }

        public float Height
        {
            get
            {
                return dimensions.Y;
            }

            
            set
            {
                changed = true;
                dimensions.Y = value;
            }
        }

        public RectangleF Bounds {
            get {
                return new RectangleF(X, Y, Width, Height);
            }

            set {
                X = value.X;
                Y = value.Y;
                Width = value.Width;
                Height = value.Height;
            }
        }

        public uint[] Elements { get {return indices; } }

        public Vector3 Rotation 
        {
            get 
            {
                return rotation;
            }

            set
            {
                changed = true;
                rotation = value;
                matRot = Matrix4x4.CreateFromYawPitchRoll(value.X, value.Y, value.Z);
            }
        }

        public ITexture Texture { get; set; }

        public Color Color { get; set; }

        public RectangleMesh(RectangleF textureRegion, ITexture texture, Color color)
        {
            this.changed = true;
            this.rotation = Vector3.Zero;
            this.origin = Vector2.Zero;
            this.dimensions = Vector2.Zero;
            this.Texture = texture;
            this.Color = color;
            this.indices = new uint[] {0, 1, 3, 1, 2, 3};
            vertices = new ValueTuple<Vector3, Vector2>[4];
            
            this.vertices[0].Item2.X = textureRegion.X;
            this.vertices[0].Item2.Y = textureRegion.Y;

            this.vertices[1].Item2.X = textureRegion.X + textureRegion.Width;
            this.vertices[1].Item2.Y = textureRegion.Y;
            
            this.vertices[2].Item2.X = textureRegion.X + textureRegion.Width;
            this.vertices[2].Item2.Y = textureRegion.Y + textureRegion.Height;
            
            this.vertices[3].Item2.X = textureRegion.X;
            this.vertices[3].Item2.Y = textureRegion.Y + textureRegion.Height;

            this.matRot = Matrix4x4.Identity;


        }

        public RectangleMesh(RectangleF meshBounds, RectangleF textureRegion, ITexture texture, Color color) : this(textureRegion, texture, color) {
            this.Bounds = meshBounds;
        }

        public RectangleMesh(ITexture texture, Color color) : this(new Rectangle(0, 0, 1, 1), texture, color) {
        }



        
        private void CalculateVertices() {
            if (!changed) return;
            Vector3[] baseVerts = new Vector3[4];
            baseVerts[0] = new Vector3(this.origin, 0);
            baseVerts[1] = new Vector3(this.origin.X + this.dimensions.X, this.origin.Y, 0);
            baseVerts[2] = new Vector3(baseVerts[1].X, this.origin.Y + this.dimensions.Y, 0);
            baseVerts[3] = new Vector3(this.origin.X, baseVerts[2].Y, 0);

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Item1 = Vector3.Transform(baseVerts[i], matRot);
            }
            changed = false;
        }
    }
}