using System;
using System.Collections.Generic;
using System.Text;
using nft.framework.drawing;
using System.Collections;
using System.Drawing;
using System.IO;
using nft.core.geometry;
using nft.framework;
using System.Diagnostics;
using System.Windows.Forms;

namespace nft.contributions.terrain {
    [Obsolete]
    public interface ITerrainImageSet<T> where T:ITerrainPolygon {
        Image this[Scaler scale, uint id, Point3DV hint] { get; }
        ITextureOld GetTexture(Scaler scl, T polygon, Point3DV hint);
    }

    [Obsolete]
    public abstract class ScaledImgCacheGenerator<T> : ITerrainImageSet<T> where T : ITerrainPolygon
    {
        protected static IList<Scaler> scalerList;
        protected readonly string ImageCacheDir;
        protected readonly string ImageFileFormat;

        static ScaledImgCacheGenerator() {
            // prepare static list which contains all scalers and each of doubled one.
            List<Scaler> list = new List<Scaler>();
            Array arr = Enum.GetValues(typeof(ZoomScale));
            foreach (ZoomScale zs in arr) {
                list.Add(Scaler.Get(zs));
                Scaler sc2 = Scaler.GetDoubled(zs);
                if (!list.Contains(sc2)) {
                    list.Add(sc2);
                }
            }
            scalerList = list;
        }

        public ScaledImgCacheGenerator(string baseDir)
            : this(baseDir, "{0:X4}.bmp") {
        }

        public ScaledImgCacheGenerator(string baseDir, string imgFilenameFormat) {
            ImageCacheDir = baseDir;
            ImageFileFormat = imgFilenameFormat;
        }

        public virtual void PrepareCache() {
            CreateSubCacheDirs();
            PrepareAllImages();
            if (textureCache != null) {
                textureCache.Clear();
            }
            textureCache = new Dictionary<UInt32, ITextureOld>(CalcPatternCounts());
        }

        public virtual void DeleteCache() {
            DeleteSubCacheDirs();
            textureCache.Clear();
        }

        protected IEnumerable SupportScalers {
            get { return scalerList; }
        }

        public virtual void DeleteSubCacheDirs() {
            foreach (Scaler sc in SupportScalers) {
                string dpath = Path.Combine(ImageCacheDir, MakeSubCacheDirName(sc));
                if (Directory.Exists(dpath))
                    Directory.Delete(dpath, true);
            }
        }

        protected void CreateSubCacheDirs() {
            foreach (Scaler sc in SupportScalers) {
                string dpath = Path.Combine(ImageCacheDir, MakeSubCacheDirName(sc));
                if (!Directory.Exists(dpath))
                    Directory.CreateDirectory(dpath);
            }
        }

        protected void PrepareAllImages() {
            foreach (Scaler scaler in SupportScalers) {
                PrepareImages(scaler);
            }
        }

        protected abstract void PrepareImages(Scaler scaler);

        protected abstract int CalcPatternCounts();

        /// <summary>
        /// Create filename for specified ID. scl is option (do not used in default implementation).
        /// </summary>
        /// <param name="scl"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        protected virtual string MakeImageFilename(Scaler scl, uint id) {
            return String.Format(ImageFileFormat, id);
        }

        /// <summary>
        /// Create sub directory name for specified Scaler
        /// </summary>
        protected string MakeSubCacheDirName(Scaler scl) {
            return scl.Value.ToString();
        }

        protected string MakeImageFullPath(Scaler scl, uint id) {
            string subdir = MakeSubCacheDirName(scl);
            string fnam = MakeImageFilename(scl, id);
            return Path.Combine(ImageCacheDir, subdir + Path.DirectorySeparatorChar + fnam);
        }

        protected Dictionary<UInt32, ITextureOld> textureCache;
        public ITextureOld GetTexture(Scaler scl, T polygon, Point3DV hint) {
            ushort id = polygon.ID;
            UInt32 key = ToCacheKey(scl, id);
            lock (textureCache) {
                if (!textureCache.ContainsKey(key)) {
                    IGraphicManagerOld gm = GlobalModules.GraphicManagerOld;
                    Rectangle region = polygon.GetBounds(scl);
                    Point off = region.Location;
                    IStaticTexture tex = gm.CreateStaticTexture(this[scl, id, hint], off);
                    tex.ColorKey = CtbGroundTextureFactory.texBGColor;
                    textureCache[key] = tex;
                    return tex;
                } else {
                    return textureCache[key];
                }
            }
        }

        protected virtual UInt32 ToCacheKey(Scaler scale, uint id) {
            return id + (UInt32)(scale.Index << 29);
        }

        #region ITerrainTextrueSet メンバ

        public Image this[Scaler scale, uint id, Point3DV hint] {
            get {
                String fullpath = MakeImageFullPath(scale, id);
                if (File.Exists(fullpath)) {
                    return Image.FromFile(fullpath);
                } else {
                    Image ret = null;
                    if (OnImageNotFound(id, out ret)) {
                        Debug.WriteLine(string.Format("Texture image not found for id={0:X}({0})", id));
                        Debug.WriteLine("FileNotFound:"+fullpath);
                    }
                    return ret;
                }
            }
        }
        #endregion

        /// <summary>
        /// Called when image file not found for specified id
        /// </summary>
        /// <param name="id">polygon id requested</param>
        /// <param name="img">alternative image object(if available) or null</param>
        /// <returns>returns false to suppress error log.</returns>
        protected virtual bool OnImageNotFound(uint id, out Image img){
            img = null;
            return true;
        }
    }

    [Obsolete]
    public abstract class AbstractGroundImgSet : ScaledImgCacheGenerator<GroundPolygon> {
        public AbstractGroundImgSet(string imageCacheDir)
            : base(imageCacheDir) {
        }

        protected override void PrepareImages(Scaler scaler) {
            Point3DV hint = new Point3DV();
            foreach (ushort id in GroundPolygon.GetAllID()) {
                GroundPolygon polygon = GroundPolygon.GetPolygon(id);
                if (polygon.IsVisible) {
                    string filepath = MakeImageFullPath(scaler, id);
                    if (!File.Exists(filepath)) {
                        Bitmap bmp = CreateBitmap(scaler, polygon, hint);
                        if (bmp != null) {
                            bmp.Save(filepath);
                            bmp.Dispose();
                        }
                    }
                }
            }
        }

        protected override int CalcPatternCounts() {
            return GroundPolygon.StockCount * (Enum.GetValues(typeof(ZoomScale)).Length + 1);
        }

        /// <summary>
        /// Should be implemented in subclass.
        /// Returned Bitmap will be disposed by caller.
        /// </summary>
        /// <param name="sc"></param>
        /// <param name="polygon"></param>
        /// <returns></returns>
        protected abstract Bitmap CreateBitmap(Scaler sc, GroundPolygon polygon, Point3DV hint);
    }

    public abstract class AbstractCliffImgSet : ScaledImgCacheGenerator<CliffPolygon> {
        public AbstractCliffImgSet(string imageCacheDir)
            : base(imageCacheDir) {
        }

        protected override void PrepareImages(Scaler scaler) {
            Point3DV hint = new Point3DV();
            foreach (ushort id in CliffPolygon.GetAllID()) {
                CliffPolygon polygon = CliffPolygon.GetPolygon(id);
                //if (polygon.IsVisible) {
                string filepath = MakeImageFullPath(scaler, id);
                if (!File.Exists(filepath)) {
                    Bitmap bmp = CreateBitmap(scaler, polygon, hint);
                    if (bmp != null) {
                        bmp.Save(filepath);
                        bmp.Dispose();
                    }
                }
            }
        }

        protected override int CalcPatternCounts() {
            return CliffPolygon.StockCount * (Enum.GetValues(typeof(ZoomScale)).Length + 1);
        }

        /// <summary>
        /// Should be implemented in subclass.
        /// Returned Bitmap will be disposed by caller.
        /// </summary>
        /// <param name="sc"></param>
        /// <param name="polygon"></param>
        /// <returns></returns>
        protected abstract Bitmap CreateBitmap(Scaler sc, CliffPolygon polygon, Point3DV hint);
    }
}
