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

namespace nft.contributions.terrain {
    public class CtbHeightCutPlaneTexture : Contribution {
        protected static Dictionary<Color, HeightCutPlaneImgSet> registerdSet = new Dictionary<Color,HeightCutPlaneImgSet>();
        protected static string CacheDirRoot;
        public readonly Color BaseColor;
        protected HeightCutPlaneImgSet imgSet;

        public CtbHeightCutPlaneTexture(Plugin p, CtbHeightCutPlaneTextureFactory factory, ParamsReader ctb)
            : base(p, ctb) {
            if (HeightCutPlaneImgSet.textureFactory == null) {
                HeightCutPlaneImgSet.textureFactory = factory;
            }
            string text = ctb["basecolor"].InnerText;
            BaseColor = ColorUtil.To12BitColor(StringParseUtil.CreateColor(text));
            CreateAndRegister(BaseColor, out imgSet);
        }

        public ITerrainImageSet<HeightCutMask> TextureSet {
            get { return imgSet; }
        }

        protected static bool CreateAndRegister(Color basecol, out HeightCutPlaneImgSet imgSet) {
            if (registerdSet.ContainsKey(basecol)) {
                imgSet = registerdSet[basecol];
                return false; // already registerd
            }
            string subdir = string.Format("{0:X6}", basecol.ToArgb() & 0xffffff);
            string path = Path.Combine(HeightCutPlaneImgSet.textureFactory.DataDirectory, subdir);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            imgSet = new HeightCutPlaneImgSet(path, basecol);
            registerdSet.Add(basecol, imgSet);
            return true;
        }

        public override void PrepareCacheData(bool forceUpdate) {
            HeightCutPlaneImgSet imgSet;
            if (!CreateAndRegister(BaseColor, out imgSet) && forceUpdate) {
                imgSet.DeleteCache();
            }
            imgSet.PrepareCache();
        }
    }

    public class HeightCutPlaneImgSet : AbstractHeightCutPlaneImgSet {
        protected internal static CtbHeightCutPlaneTextureFactory textureFactory;
        public readonly Color BaseColor;
        public readonly Color BackgroundColor;
        internal protected HeightCutPlaneImgSet(string imageCacheDir, Color basecol) 
            : base(imageCacheDir) {
            this.BaseColor = basecol;
            int v = BaseColor.ToArgb() & 0xc0c0c0;
            v ^= 0xc000c0;
            this.BackgroundColor = v == 0 ? Color.Green : Color.Magenta;
        }

        protected override Bitmap CreateBitmap(Scaler sc, GroundPolygon pBase, HeightCutMask pMask, Point3DV hint) {
            Point[] pts = pBase.GetVerticis(sc);
            Rectangle r1 = Rectangle.Empty;
            Bitmap bmp = PrimitiveTextrueFactory.CreatePolygonBitmap(pts, BaseColor, BackgroundColor, ref r1);
            HeightCutMaskImgSet imgset = HeightCutMaskImgSet.GetOrCreate(BackgroundColor);
            r1 = pBase.GetBounds(sc);
            Rectangle r2 = pMask.GetBounds(sc);
            //r2.Intersect(r1);
            if (r2.Width * r2.Height > 0)
            {
                Bitmap img = imgset[sc, pMask.ID, hint] as Bitmap;
                if (img != null)
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        img.MakeTransparent(imgset.BackgroundColor);
                        g.DrawImage(img, r2.X - r1.X, r2.Y - r1.Y);
                        img.Dispose();
                    }
                }
            }
            return bmp;
        }
    }

    public class CtbHeightCutSlopeTexture : Contribution {
        protected static Dictionary<Color, HeightCutSlopeImgSet> registerdSet = new Dictionary<Color, HeightCutSlopeImgSet>();
        protected static string CacheDirRoot;
        public readonly Color BaseColor;
        protected HeightCutSlopeImgSet imgSet;

        public CtbHeightCutSlopeTexture(Plugin p, CtbHeightCutSlopeTextureFactory factory, ParamsReader ctb)
            : base(p, ctb) {
            if (HeightCutSlopeImgSet.textureFactory == null) {
                HeightCutSlopeImgSet.textureFactory = factory;
            } 
            string text = ctb["basecolor"].InnerText;
            BaseColor = ColorUtil.To12BitColor(StringParseUtil.CreateColor(text));
            CreateAndRegister(BaseColor, out imgSet);
        }

        public ITerrainImageSet<HeightCutSlopePolygon> TextureSet {
            get { return imgSet; }
        }

        protected static bool CreateAndRegister(Color basecol, out HeightCutSlopeImgSet imgSet) {
            if (registerdSet.ContainsKey(basecol)) {
                imgSet = registerdSet[basecol];
                return false; // already registerd
            }
            imgSet = HeightCutSlopeImgSet.GetOrCreate(basecol);
            registerdSet.Add(basecol, imgSet);
            return true;
        }

        public override void PrepareCacheData(bool forceUpdate) {
            HeightCutSlopeImgSet imgSet;
            if (!CreateAndRegister(BaseColor, out imgSet) && forceUpdate) {
                imgSet.DeleteCache();
            }
            imgSet.PrepareCache();
        }

        public class HeightCutSlopeImgSet : AbstractHeightCutSlopeImgSet {
            protected internal static CtbHeightCutSlopeTextureFactory textureFactory;
            private static Dictionary<Color, HeightCutSlopeImgSet> cache
                = new Dictionary<Color, HeightCutSlopeImgSet>(8);
            public static HeightCutSlopeImgSet GetOrCreate(Color foreground) {
                HeightCutSlopeImgSet ret;
                if (cache.TryGetValue(foreground, out ret)) return ret;

                int rgb = foreground.ToArgb();
                string subdir = string.Format("{0:X6}", rgb & 0xffffff);
                string path = Path.Combine(HeightCutSlopeImgSet.textureFactory.DataDirectory, subdir);
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                /*
                rgb &= 0xc0c0c0;
                rgb ^= 0x00c000;
                Color bg = (rgb == 0) ? Color.Magenta : Color.Lime;
                 */
                ret = new HeightCutSlopeImgSet(path, foreground);
                ret.PrepareCache();
                cache.Add(foreground, ret);
                return ret;
            }

            protected readonly Color texBGColor;
            protected readonly Color texFGColor;

            public HeightCutSlopeImgSet(string imageCacheDir, Color fore)
                : base(imageCacheDir) {
                texFGColor = fore;
                // Due to the sprite creation process(see CreateBitmap), 
                // Backgorund color is restricted to the 'texBGColor'
                texBGColor = CtbGroundTextureFactory.texBGColor;
            }

            public Color BackgroundColor { get { return texBGColor; } }
            public Color ForegroundColor { get { return texFGColor; } }

            protected override Bitmap CreateBitmap(Scaler sc, HeightCutSlopePolygon polygon, Point3DV hint) {
                //throw new NotImplementedException();
                return null;
            }
        }

    }
}
