using System;
using System.Collections.Generic;
using System.Text;
using CommonUI.Display;
using CommonLang;
using CommonUI.Gemo;

namespace CommonUI.Cell
{
    public abstract class CPJAtlas : IDisposable
    {
        protected CPJResource set;
        protected ImagesSet img;
        private HashMap<String, int> imageKeys;

        public abstract void ReleaseTexture();
        public CPJAtlas(ImagesSet img, CPJResource res)
        {
            this.set = res;
            this.img = img;
            this.imageKeys = new HashMap<String, int>();
            for(int i = 0; i < img.Count; i++)
            {
                if(img.ClipsKey[i] != null && !string.IsNullOrEmpty(img.ClipsKey[i]))
                {
                    imageKeys.Put(img.ClipsKey[i], i);
                }
            }
        }
        public ImagesSet ImagesSet { get { return img; } }

        public int Count { get { return img.Count; } }

        public bool IsNullTile(int index)
        {
            return img.getClipW(index) == 0;
        }
        
        abstract public Image GetTile(int index);

        /// <summary>
        /// 获取渲染图片区域
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        abstract public Rectangle2D GetAtlasRegion(int index);

        public Rectangle2D GetClipRect(int index)
        {
            return new Rectangle2D(
                    img.getClipX(index),
                    img.getClipY(index),
                    img.getClipW(index),
                    img.getClipH(index));
        }


        public int getWidth(int Index)
        {
            return img.getClipW(Index);
        }

        public int getHeight(int Index)
        {
            return img.getClipH(Index);
        }

        public void render(Graphics g, string key, float x, float y, Trans trans)
        {
            if(imageKeys.ContainsKey(key))
            {
                int index = imageKeys[key];
                render(g, index, x, y, trans);
            }
        }

        public int GetIndexByKey(string key)
        {
            int ret = -1;
            if(imageKeys.TryGetValue(key, out ret))
            {
                return ret;
            }
            return -1;
        }

        abstract public void render(Graphics g, int index, float x, float y, Trans trans);

        abstract public void begin(Graphics g);

        abstract public void addVertex(VertexBuffer v, int index, float x, float y, Trans trans, uint color_rgba);

        public virtual void Dispose()
        {
            img = null;
            set = null;  
            if(imageKeys != null)
            {
                imageKeys.Clear();
                imageKeys = null;
            }

        }

    }

    //------------------------------------------


    public class CPJAtlasGroup : CPJAtlas
    {
        private Image atlas;

        public CPJAtlasGroup(ImagesSet img, CPJResource res)
            : base(img, res)
        {
            atlas = res.Loader.LoadImage(img.Name + "." + img.Extention);
        }
        

        override public Image GetTile(int index)
        {
            return atlas;
        }
        override public Rectangle2D GetAtlasRegion(int index)
        {
            return new Rectangle2D(
                img.ClipsX[index],
                img.ClipsY[index],
                img.ClipsW[index],
                img.ClipsH[index]);
        }
        override public void render(Graphics g, int index, float x, float y, Trans trans)
        {
            if(img.ClipsW[index] > 0)
            {
                g.drawRegion(atlas,
                    img.ClipsX[index],
                    img.ClipsY[index],
                    img.ClipsW[index],
                    img.ClipsH[index],
                    trans, x, y
                    );
            }
        }

        override public void begin(Graphics g)
        {
            g.beginImage(atlas);
        }
        override public void addVertex(VertexBuffer v, int index, float x, float y, Trans trans, uint color_rgba)
        {
            if (img.ClipsW[index] > 0)
            {
                VertexUtils.AddImageQuard(v, atlas, color_rgba,
                    img.ClipsX[index],
                    img.ClipsY[index],
                    img.ClipsW[index],
                    img.ClipsH[index],
                    trans, x, y);
            }
        }
        override public void Dispose()
        {
            if(atlas != null)
            {
                atlas.Dispose();
                atlas = null;
            }
      
            base.Dispose();
        }

        public override void ReleaseTexture()
        {
            if (atlas != null)
            {
                atlas.ReleaseTexture();
            }
        }

    }

    public class CPJAtlasSplitGroup : CPJAtlas
    {
        private Image[,] mPartMatrix;
        private int mSplitSize;
        private int mPartCountX;
        private int mPartCountY;

        public CPJAtlasSplitGroup(ImagesSet img, CPJResource res)
            : base(img, res)
        {
            mSplitSize = img.SplitSize;
            mPartCountX = (int)CMath.ccNextPOT(img.TotalW) / mSplitSize;
            mPartCountY = (int)CMath.ccNextPOT(img.TotalH) / mSplitSize;
            mPartMatrix = new Image[mPartCountX, mPartCountY];
            for(int x = 0; x < mPartCountX; x++)
            {
                for(int y = 0; y < mPartCountY; y++)
                {
                    string img_path = string.Format("{0}_{1}_{2}.{3}", img.Name, x, y, img.Extention);
                    mPartMatrix[x, y] = res.Loader.LoadImage(img_path);
                }
            }
        }
        

        override public Image GetTile(int index)
        {
            int bx = ((int)img.ClipsX[index]) / mSplitSize;
            int by = ((int)img.ClipsY[index]) / mSplitSize;
            Image pTexture = mPartMatrix[bx, by];
            return pTexture;
        }
        override public Rectangle2D GetAtlasRegion(int index)
        {
            return new Rectangle2D(
                img.ClipsX[index] % mSplitSize,
                img.ClipsY[index] % mSplitSize,
                img.ClipsW[index],
                img.ClipsH[index]);
        }

        override public void render(Graphics g, int index, float x, float y, Trans trans)
        {
            if(img.ClipsW[index] > 0)
            {
                int bx = ((int)img.ClipsX[index]) / mSplitSize;
                int by = ((int)img.ClipsY[index]) / mSplitSize;
                Image pTexture = mPartMatrix[bx, by];
                if(pTexture != null)
                {
                    g.drawRegion(pTexture,
                        img.ClipsX[index] % mSplitSize,
                        img.ClipsY[index] % mSplitSize,
                        img.ClipsW[index],
                        img.ClipsH[index],
                        trans, x, y);
                }
            }
        }
        override public void begin(Graphics g)
        {
            throw new NotImplementedException();
        }
        override public void addVertex(VertexBuffer v, int index, float x, float y, Trans trans, uint color_rgba)
        {
            throw new NotImplementedException();
        }

        override public void Dispose()
        {
            foreach(Image img in mPartMatrix)
            {
                img.Dispose();
            }
          
            base.Dispose();
        }
        public override void ReleaseTexture()
        {
            for (int x = 0; x < mPartCountX; x++)
            {
                for (int y = 0; y < mPartCountY; y++)
                {
                    mPartMatrix[x, y].ReleaseTexture();
                }
            }
 
        }
    }

    public class CPJAtlasTiles : CPJAtlas
    {
        private Image[] tiles;

        public CPJAtlasTiles(ImagesSet img, CPJResource res)
            : base(img, res)
        {
            tiles = new Image[img.Count];
            for(int i = 0; i < img.Count; i++)
            {
                if(img.ClipsW[i] > 0 && img.ClipsH[i] > 0)
                {
                    tiles[i] = res.Loader.LoadImage(img.Name + "/" + i + "." + img.Extention);
                }
            }
        }

        override public Image GetTile(int index)
        {
            return tiles[index];
        }

        override public Rectangle2D GetAtlasRegion(int index)
        {
            return new Rectangle2D(0, 0, img.ClipsW[index], img.ClipsH[index]);
        }

        override public void render(Graphics g, int index, float x, float y, Trans trans)
        {
            Image tile = tiles[index];
            if(tile != null)
            {
                g.drawImageTrans(tile, x, y, trans);
            }
        }
        override public void begin(Graphics g)
        {
            throw new NotImplementedException();
        }
        override public void addVertex(VertexBuffer v, int index, float x, float y, Trans trans, uint color_rgba)
        {
            throw new NotImplementedException();
        }

        override public void Dispose()
        {
            for(int i = 0; i < img.Count; i++)
            {
                if(tiles[i] != null)
                {
                    tiles[i].Dispose();
                }
            }
            tiles = null;
            base.Dispose();
        }
        public override void ReleaseTexture()
        {
            for (int i = 0; i < img.Count; i++)
            {
                if (img.ClipsW[i] > 0 && img.ClipsH[i] > 0)
                {
                    tiles[i].ReleaseTexture();
                }
            }
 
        }
    }

}