using System;
using System.Collections.Generic;
using System.Text;
using CommonUI.Display;
using UnityEngine;
using System.IO;
using CommonUI_Unity3D.Src.M3Z;
using CommonLang.IO;
using CommonUI_Unity3D.Impl;
using UnityEngine.Internal;

namespace CommonUI_Unity3D.Impl
{
  

    public class UnityImage : Image, IUnityImageInterface
    {
        private Texture2D mTexture;
        private Texture2D mTextureMask;
        internal int mLogicW, mLogicH;
        internal float mMaxU, mMaxV;
        private Material mMaterial;
        private string mResStr;
        public string ResourceStr
        {
            get
            {
                return mResStr;
            }
        }
        public bool SupportReleaseTexture { get; set; }
        internal static void FilterTexture(Texture2D tex)
        {
            tex.filterMode = FilterMode.Bilinear;
            tex.wrapMode = TextureWrapMode.Clamp;
            tex.anisoLevel = 2;
            tex.mipMapBias = 0;
        }

        public UnityImage(Texture2D tex, string name,string res = null)
        {
            mResStr = res;
            SupportReleaseTexture = true;
            ResestTexture2D(tex, name);
        }
        public UnityImage(Texture2D tex, int logicW, int logicH, string name, string res = null)
        {
            mResStr = res;
            SupportReleaseTexture = true;
            ResestTexture2D(tex, logicW, logicH, name);
        }

        public UnityImage(byte[] data, string name, string res = null)
        {
            mResStr = res;
            SupportReleaseTexture = true;
            ResestTexture2D(data, name);
        }

        public override void ReleaseTexture()
        {
            //有ResourceStr才允许释放贴
            if (SupportReleaseTexture && !string.IsNullOrEmpty(mResStr))
            {
                if (mTexture != null)
                {
                    Texture2D.Destroy(mTexture);
                    mTexture = null;
                }
                if (mTextureMask != null)
                {
                    Texture2D.Destroy(mTextureMask);
                    mTextureMask = null;
                }
                if (mMaterial != null)
                {
                    Material.Destroy(mMaterial);
                    mMaterial = null;
                }
            }
        }

        private void CheckReload()
        {
            if(mTexture == null)
            {
                Driver.Instance.ReloadImage(this);
            }
        }

        public void ResestTexture2D(Texture2D tex, string name)
        {
            this.name = name;
            this.mTexture = tex;
            this.mTexture.name = name;
            FilterTexture(mTexture);
            this.mLogicW = tex.width;
            this.mLogicH = tex.height;
            this.mMaxU = 1f;
            this.mMaxV = 1f;
        }

        public void ResestTexture2D(Texture2D tex, int logicW, int logicH, string name)
        {
            this.name = name;
            this.mTexture = tex;
            this.mTexture.name = name;
            FilterTexture(mTexture);
            this.mLogicW = logicW;
            this.mLogicH = logicH;
            this.mMaxU = Math.Min(mLogicW / (float)tex.width, 1f);
            this.mMaxV = Math.Min(mLogicH / (float)tex.height, 1f);
        }

        public void ResestTexture2D(byte[] data, string name)
        {
            this.name = name;
            string ext = name.ToLower();
            if (ext.EndsWith(".m3z"))
            {
                using (var input = new MemoryStream(data, false))
                {
                    M3ZHeader m3z = new M3ZHeader(input);
                    InitWithM3Z(m3z);
                }
            }
            else if (ext.EndsWith(".g3z"))
            {
                using (var input = G3ZStream.DecompressToStream(data))
                {
                    M3ZHeader m3z = new M3ZHeader(input);
                    InitWithM3Z(m3z);
                }
            }
            else
            {
                this.mTexture = new Texture2D(1, 1, TextureFormat.RGBA32, false, true);
                this.mTexture.name = name;
                this.mTexture.LoadImage(data, true);
                FilterTexture(mTexture);
                this.mLogicW = mTexture.width;
                this.mLogicH = mTexture.height;
                this.mMaxU = 1;
                this.mMaxV = 1;
            }
        }

        private void InitWithM3Z(M3ZHeader header)
        {
            this.mMaxU = 1;
            this.mMaxV = 1;
#if UNITY_EDITOR
            Debug.Log(string.Format("InitM3Z : {0} : format={1} src={2}x{3} pot={4}x{5}",
                    name,
                    header.trunks[0].type,
                    header.srcWidth,
                    header.srcHeight,
                    header.trunks[0].pixelW,
                    header.trunks[0].pixelH));
#endif
            if (header.trunks.Length > 0)
            {
                this.mTexture = header.trunks[0].LoadRawTextureData();
                this.mTexture.name = name + "(Trunk0)";
                FilterTexture(this.mTexture);
            }
            if (header.trunks.Length > 1)
            {
                this.mTextureMask = header.trunks[1].LoadRawTextureData();
                this.mTextureMask.name = name + "(Trunk1)";
                FilterTexture(this.mTextureMask);
            }
            this.mLogicW = header.srcWidth;
            this.mLogicH = header.srcHeight;
            this.mMaxU = Math.Min(mLogicW / (float)mTexture.width, 1f);
            this.mMaxV = Math.Min(mLogicH / (float)mTexture.height, 1f);
            header = null;
        }
        //-----------------------------------------------------------------------------------------------------------
        public override int Width { get { return mLogicW; } }
        public override int Height { get { return mLogicH; } }
        public override float MaxU { get { return mMaxU; } }
        public override float MaxV { get { return mMaxV; } }
        public Texture Texture { get { return Texture2D; } }
        public Texture TextureMask { get { return Texture2DMask; } }
        public Texture2D Texture2D { get { CheckReload(); return mTexture; } }
        public Texture2D Texture2DMask { get { CheckReload(); return mTextureMask; } }

        public Material TextureMaterial { get { return GetMaterial(); } }
        //-----------------------------------------------------------------------------------------------------------
        public Material GetMaterial()
        {
            CheckReload();
            if (mMaterial == null)
            {
                mMaterial = UnityShaders.CreateMaterialUGUI(this);
            }
            return mMaterial;
        }
        protected override void Disposing()
        {
            if (mTexture != null)
            {
                Texture2D.Destroy(mTexture);
                mTexture = null;
            }
            if (mTextureMask != null)
            {
                Texture2D.Destroy(mTextureMask);
                mTextureMask = null;
            }
            if (mMaterial != null)
            {
                Material.Destroy(mMaterial);
                mMaterial = null;
            }
        }

        public override void CopyPixels(Image src, int sx, int sy, int sw, int sh, int dx, int dy)
        {
            UnityImage srci = src as UnityImage;
            UnityDriver.Platform.CopyPixels(srci.mTexture, sx, sy, sw, sh, this.mTexture, dx, dy);
        }

        public override void Flush()
        {
            mTexture.Apply();
        }

        public Texture GetTexture()
        {
            return mTexture;
        }

        public Texture GetTextureMask()
        {
            return mTextureMask;
        }

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


    }
}