using System.Collections.Generic;
using System.Drawing;

namespace MyScreenCap.Ctrl {

    /// <summary>
    /// MedianCutBox
    /// </summary>
    public class MedianCutBox {

        /// <summary>
        /// RGBのMax・Min
        /// </summary>
        private int RMax { get; set; }
        private int RMin { get; set; }
        private int GMax { get; set; }
        private int GMin { get; set; }
        private int BMax { get; set; }
        private int BMin { get; set; }

        /// <summary>
        /// Boxに含まれる色
        /// </summary>
        public List<Color> ColorList { get; set; }

        /// <summary>
        /// RGB軸
        /// </summary>
        private enum Axis {
            R,
            G,
            B,
        }

        /// <summary>
        /// 分割軸
        /// </summary>
        private Axis CutAxis { get; set; }

        /// <summary>
        /// MedianCutBoxの中心の色を取得
        /// </summary>
        public Color Color {
            get {
                int r = 0;
                int g = 0;
                int b = 0;

                foreach (Color color in ColorList) {
                    r += color.R;
                    g += color.G;
                    b += color.B;
                }
                r /= ColorList.Count;
                g /= ColorList.Count;
                b /= ColorList.Count;
                return Color.FromArgb(r, g, b);
            }
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="colorList"></param>
        public MedianCutBox(List<Color> colorList) {
            ColorList = colorList;
            GetRGBMaxLength();
        }

        /// <summary>
        /// MedianCutBoxの分割
        /// </summary>
        /// <param name="box1">分割されたBox</param>
        /// <param name="box2">分割されたBox</param>
        public void CutBox(out MedianCutBox box1, out MedianCutBox box2) {
            SortColorList();

            int cutIndex = ColorList.Count / 2;

            box1 = new MedianCutBox(ColorList.GetRange(0, cutIndex));
            box2 = new MedianCutBox(ColorList.GetRange(cutIndex, ColorList.Count - cutIndex));
        }

        /// <summary>
        /// 分割軸を決定
        /// </summary>
        private void GetRGBMaxLength() {
            int maxLenghtTmp;
            int maxLength;

            RMax = 0;
            RMin = 255;
            GMax = 0;
            GMin = 255;
            BMax = 0;
            BMin = 255;
            foreach (Color color in ColorList) {
                if (RMin > color.R) {
                    RMin = color.R;
                } else if (RMax < color.R) {
                    RMax = color.R;
                }

                if (GMin > color.G) {
                    GMin = color.G;
                } else if (GMax < color.G) {
                    GMax = color.G;
                }

                if (BMin > color.B) {
                    BMin = color.B;
                } else if (BMax < color.B) {
                    BMax = color.B;
                }
            }

            CutAxis = Axis.R;
            maxLength = (RMax - RMin) * 10;

            maxLenghtTmp = (GMax - GMin) * 8;
            if (maxLength < maxLenghtTmp) {
                maxLength = maxLenghtTmp;
                CutAxis = Axis.G;
            }

            maxLenghtTmp = (BMax - BMin) * 5;
            if (maxLength < maxLenghtTmp) {
                CutAxis = Axis.B;
            }

        }

        /// <summary>
        /// ColorListのソート
        /// </summary>
        private void SortColorList() {
            switch (CutAxis) {
                case Axis.R:
                    CompareR compR = new CompareR();
                    ColorList.Sort(compR);
                    break;
                case Axis.G:
                    CompareG compG = new CompareG();
                    ColorList.Sort(compG);
                    break;
                case Axis.B:
                    CompareB compB = new CompareB();
                    ColorList.Sort(compB);
                    break;
            }
        }

        /// <summary>
        /// Rでソート用
        /// </summary>
        private class CompareR : IComparer<Color> {
            public int Compare(Color color1, Color color2) {
                return color1.R.CompareTo(color2.R);
            }
        }
        /// <summary>
        /// Gでソート用
        /// </summary>
        private class CompareG : IComparer<Color> {
            public int Compare(Color color1, Color color2) {
                return color1.G.CompareTo(color2.G);
            }
        }
        /// <summary>
        /// Bでソート用
        /// </summary>
        private class CompareB : IComparer<Color> {
            public int Compare(Color color1, Color color2) {
                return color1.B.CompareTo(color2.B);
            }
        }
    }
}
