using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VisiMath;

namespace VisimBox.Renderer.Render2D
{
        

    public struct Vertex2D
    {
        public Vector2 Pos;
        public Vector2 Tex;
    }

    /// <summary>
    /// Information for 2d sprite - Target rectangle in pixel coordinates, source texture coordinates in relative values
    /// </summary>
    public struct SpriteInfo
    {
        /*
        /// <summary>
        /// Target rectangle in pixel coordinates
        /// </summary>
        public System.Drawing.Rectangle Target;
        /// <summary>
        /// Source rectangle from texture in relative coordiantes (0 - 1)
        /// </summary>
        public System.Drawing.RectangleF Source;

        public SpriteInfo(int tx, int ty, int width, int height, float sx, float sy, float swidth, float sheight)
        {
            Target = new System.Drawing.Rectangle(tx, ty, width, height);
            Source = new System.Drawing.RectangleF(sx, sy, swidth, sheight);
        }
        */

        public Vertex2D[] Vertices;

        public SpriteInfo(int tx, int ty, int width, int height, float sx, float sy, float swidth, float sheight)
        {
            Vertices = new Vertex2D[4];
            Vertices[0].Pos = new Vector2(tx, ty);
            Vertices[1].Pos = new Vector2(tx+width, ty);
            Vertices[2].Pos = new Vector2(tx + width, ty + height);
            Vertices[3].Pos = new Vector2(tx, ty + height);

            Vertices[0].Tex = new Vector2(sx, sy);
            Vertices[1].Tex = new Vector2(sx+swidth, sy);
            Vertices[2].Tex = new Vector2(sx + swidth, sy + sheight);
            Vertices[3].Tex = new Vector2(sx, sy + sheight);
        }
    }

    /// <summary>
    /// Batch of the sprites and associated texture
    /// </summary>
    public struct SpriteBatch : IDisposable, Resources.IResourceConsumer
    {
        //NOTE!!! counts reference, but is struct... should probably change to class and don't create new on each call...

        /// <summary>
        /// Array of sprites
        /// </summary>
        //public SpriteInfo[] Sprites;

        public Vertex2D[] Vertices;

        /// <summary>
        /// Associated texture
        /// </summary>
        public Texture Texture {get {return _Texture;}}

        private Texture _Texture;

        public SpriteBatch(Texture t, List<SpriteInfo> list)
        {
            _Texture = t;

            Vertices = new Vertex2D[4 * list.Count];

            for (int i = 0; i < list.Count; i++)
            {
                for (int j = 0; j < 4; j++)
                    Vertices[i * 4 + j] = list[i].Vertices[j];
            }

            _Texture.AddReference(this);

        }

        public SpriteBatch(Texture t, SpriteInfo[] sprites)
        {
            _Texture = t;
            //Sprites = sprites;

            Vertices = new Vertex2D[4 * sprites.Length];

            for (int i = 0; i < sprites.Length; i++)
            {
                for (int j = 0; j < 4; j++)
                    Vertices[i * 4 + j] = sprites[i].Vertices[j];
            }
            _Texture.AddReference(this);
        }

        public SpriteBatch(Texture t, List<Vertex2D> list)
        {
            _Texture = t;
            Vertices = list.ToArray();
            _Texture.AddReference(this);
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (_Texture != null)
            {
                _Texture.RemoveReference(this);
                _Texture = null;
            }
        }

        #endregion

        #region IResourceConsumer Members

        public void ResourceDisposing(Resources.IResource resource)
        {
            if ((resource as Texture) == _Texture)
                _Texture = null;
        }

        public bool ResourceReplaced(Resources.IResource original, Resources.IResource newresource)
        {
            if ((original as Texture) == _Texture)
            {
                Texture newtex = newresource as Texture;
                if (newtex != null)
                {
                    _Texture = newtex;
                    //reference handled by caller
                    return true;
                }
            }
            return false;
        }

        #endregion
    }

}
