using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;

namespace RecrownedAthenaeum.Render
{
    /// <summary>
    /// Renders rectangles using the <see cref="PrimitiveBatch"/>.
    /// </summary>
    public class RectangleRenderer : IDisposable
    {
        private bool filled;
        private bool disposed;
        /// <summary>
        /// The <see cref="PrimitiveBatch"/> used. Needs to be disposed.
        /// </summary>
        private readonly PrimitiveBatch primitiveBatch;

        /// <summary>
        /// Creates a rectangle renderer with the given <see cref="PrimitiveBatch"/>.
        /// </summary>
        /// <param name="graphicsDevice">Graphics device to use.</param>
        public RectangleRenderer(GraphicsDevice graphicsDevice)
        {
            primitiveBatch = new PrimitiveBatch(graphicsDevice);
        }

        /// <summary>
        /// Disposes the rectangle renderer.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }

        /// <summary>
        /// Overridable for dispose.
        /// </summary>
        /// <param name="disposing">True when its a player calling the dispose.</param>
        public virtual void Dispose(bool disposing)
        {
            if (disposed) throw new ObjectDisposedException(GetType().Name);
            if (disposing)
            {
                primitiveBatch.Dispose();
            }
            disposed = true;
        }

        /// <summary>
        /// Begins a batch for rectangles.
        /// </summary>
        /// <param name="filled">Whether or not this batch should be filled rectangles.</param>
        public void Begin(bool filled = false)
        {
            this.filled = filled;
            primitiveBatch.Begin(filled ? PrimitiveType.TriangleStrip : PrimitiveType.LineStrip);
        }

        /// <summary>
        /// Ends the batch.
        /// </summary>
        public void End()
        {
            primitiveBatch.End();
        }
        /// <summary>
        /// Draws a basic rectangle given bottom left and top right.
        /// </summary>
        /// <param name="x">X coordinate of bottom left.</param>
        /// <param name="y">Y coordinate of bottom left.</param>
        /// <param name="width">Width of rectangle.</param>
        /// <param name="height">Height of rectangle.</param>
        /// <param name="color">Color of all vertices of this rectangle.</param>
        /// <param name="rotation">Rotation of rectangle. Default is 0 radians.</param>
        public void Draw(int x, int y, int width, int height, Color color, float rotation = 0)
        {
            primitiveBatch.primitiveCount = filled ? 3 : 4;
            Vector2[] corners = new Vector2[4];
            corners[1] = new Vector2(width, 0);
            corners[2] = new Vector2(width, height);
            corners[3] = new Vector2(0, height);

            if (rotation != 0)
            {
                Matrix rotMat = Matrix.CreateRotationZ(rotation);
                for (int i = 0; i < corners.Length; i++)
                {
                    corners[i] = Vector2.Transform(corners[i], rotMat);
                }
            }

            for (int i = 0; i < corners.Length; i++)
            {
                corners[i].X += x;
                corners[i].Y += y;
            }

            primitiveBatch.AddVertex(corners[0], color);
            primitiveBatch.AddVertex(corners[1], color);
            primitiveBatch.AddVertex(corners[2], color);
            primitiveBatch.AddVertex(corners[3], color);
            primitiveBatch.AddVertex(corners[0], color);

            primitiveBatch.Flush();
        }

        /// <summary>
        /// Draws the given rectangle.
        /// </summary>
        /// <param name="rectangle">Uses the x, y and dimensions to draw a rectangle.</param>
        /// <param name="color">The color of the rectangle.</param>
        public void Draw(Rectangle rectangle, Color color)
        {
            Draw(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, color);
        }
    }
}
