using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Xml;
using nft.framework;
using nft.framework.plugin;
using nft.core.game;
using nft.core.geometry;
using nft.core.structure;
using nft.util;
using nft.framework.drawing;
using System.Text;
using System.IO;
using System.Collections.Generic;

namespace nft.contributions.terrain
{
	/// <summary>
    /// CtbTerrainTextureFactory の概要の説明です。
	/// </summary>
    public class CtbHeightCutPlaneTextureFactory : CtbCustomCtbFactory
	{
        //private static CtbTerrainTextureFactory theInstance;
        //public static ITexture GetSilhouetteTexture(Scaler scl, short id) {
        //    return theInstance.GetTexture(scl, id);
        //}
        
        public CtbHeightCutPlaneTextureFactory(Plugin p, XmlElement contrib)
            : base(p, contrib) {
        }

        protected override Contribution  Create(Plugin owner, XmlElement e)
        {
            //TODO:将来テクスチャ画像対応の地形テクスチャも…
            return new CtbHeightCutPlaneTexture(owner, this, e);
        }
    }

    public class CtbHeightCutSlopeTextureFactory : CtbCustomCtbFactory {
        public CtbHeightCutSlopeTextureFactory(Plugin p, XmlElement contrib)
            : base(p, contrib) {
        }

        protected override Contribution Create(Plugin owner, XmlElement e) {
            //TODO:将来テクスチャ画像対応の地形テクスチャも…
            return new CtbHeightCutSlopeTexture(owner, this, e);
        }
    }

    public abstract class AbstractHeightCutPlaneImgSet : ScaledImgCacheGenerator<HeightCutMask> {
        static private GroundPolygon[] patternBase;
        static AbstractHeightCutPlaneImgSet() {
            patternBase = new GroundPolygon[4];
            patternBase[(int)ViewDirection.FRONT] = GroundPolygon.GetPolygon(0, 0, 0, -1);
            patternBase[(int)ViewDirection.LEFT] = GroundPolygon.GetPolygon(0, 0, -1, 0);
            patternBase[(int)ViewDirection.RIGHT] = GroundPolygon.GetPolygon(0, -1, 0, 0);
            patternBase[(int)ViewDirection.BEHIND] = GroundPolygon.GetPolygon(-1, 0, 0, 0);
        }

        static protected GroundPolygon GetBasePattern(ViewDirection vd) {
            return patternBase[(int)vd];
        }

        public AbstractHeightCutPlaneImgSet(string imageCacheDir)
            : base(imageCacheDir) {
        }

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

        protected override int CalcPatternCounts() {
            return HeightCutMask.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 pBase, HeightCutMask pMask, Point3DV hint);
    }

    public abstract class AbstractHeightCutSlopeImgSet : ScaledImgCacheGenerator<HeightCutSlopePolygon> {

        public AbstractHeightCutSlopeImgSet(string imageCacheDir)
            : base(imageCacheDir, "{0:X5}.bmp") {
        }

        public AbstractHeightCutSlopeImgSet(string imageCacheDir, string fnformat)
            : base(imageCacheDir, fnformat) {
        }

        protected override void PrepareImages(Scaler scaler) {
            Point3DV hint = new Point3DV();
            foreach (uint id in HeightCutSlopePolygon.GetAllID()) {
                HeightCutSlopePolygon polygon = HeightCutSlopePolygon.GetPolygon(id);
                if (!polygon.BasePolygon.IsVisible) continue;
                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 HeightCutSlopePolygon.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, HeightCutSlopePolygon polygon, Point3DV hint);
    }
}
