using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Newtonsoft.Json;
using System.Collections;

namespace Misc
{
    /// <summary>
    /// int范围类， 
    /// </summary>
    public struct RangeStruct
    {
        #region property
        /// <summary>
        /// 开始
        /// </summary>
        public int Begin { get; set; }

        /// <summary>
        /// 结束
        /// </summary>
        public int End { get; set; }
        #endregion

        #region just get property
        /// <summary>
        /// 本范围 中心位置
        /// </summary>
        [JsonIgnore]
        public int Mid
        {
            get
            {
                if (Misc.MyBase.ISVALIDATA(Begin))
                    return (End + Begin) / 2;
                else
                    return Misc.MyBase.NULL_VALUE;
            }
        }

        /// <summary>
        /// 本范围宽度
        /// </summary>
        [JsonIgnore]
        public int Width
        {
            get
            {
                if (IsValid)
                    return End - Begin + 1;
                else
                    return Misc.MyBase.NULL_VALUE;
            }
        }


        /// <summary>
        /// 是否有效
        /// </summary>
        [JsonIgnore]
        public bool IsValid
        {
            get
            {
                if (Misc.MyBase.ISVALIDATA(Begin) && Misc.MyBase.ISVALIDATA(End))
                    return true;
                else
                    return false;
            }
        }
        #endregion

        public RangeStruct(int begin, int end) {
            Begin = begin;
            End = end;
        }

        #region methods


        /// <summary>
        /// 范围 r 在 本范围内
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool Contain(RangeStruct r)
        {
            if ((Begin <= r.Begin) && (r.End <= End))
                return true;
            else
                return false;
        }

        /// <summary>
        /// 点 p 在 本范围内
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public bool Contain(int p)
        {
            if ((Begin <= p) && (p <= End))
                return true;
            else
                return false;
        }

        /// <summary>
        /// 无效值
        /// </summary>
        public static RangeStruct InvalidValue
        {
            get {
                return new RangeStruct(Misc.MyBase.NULL_VALUE, Misc.MyBase.NULL_VALUE);
            }
        }




        /// <summary>
        /// 范围并集
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static RangeStruct operator |(RangeStruct a, RangeStruct b)
        {
            return new RangeStruct()
            {
                Begin = (a.Begin < b.Begin) ? a.Begin : b.Begin,
                End = (a.End > b.End) ? a.End : b.End
            };
        }

        /// <summary>
        /// 范围交集
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static RangeStruct operator &(RangeStruct a, RangeStruct b)
        {
            RangeStruct r = new RangeStruct()
            {
                Begin = (a.Begin > b.Begin) ? a.Begin : b.Begin,
                End = (a.End < b.End) ? a.End : b.End
            };
            if (r.End < r.Begin)
            {
                return InvalidValue;
            }
            else
            {
                return r;
            }
        }
        /// <summary>
        /// 范围 减
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static RangeStruct operator -(RangeStruct a, RangeStruct b)
        {
            if (a.Begin < b.Begin)
            {
                return new RangeStruct(a.Begin, b.Begin - 1);
            }
            else {
                if (a.End > b.End)
                    return new RangeStruct(b.End + 1, a.End);
                else
                    return InvalidValue;
            }
        }
        /// <summary>
        /// 范围 a小于b
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator <(RangeStruct a, RangeStruct b)
        {
            if (a.End < b.Begin)//[a.b,a.e] [b.b,b.e]
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 范围 a大于b
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator >(RangeStruct a, RangeStruct b)
        {
            if (b.End < (a.Begin))// [b.b,b.e][a.b,a.e]
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public static bool operator <(int p, RangeStruct r)
        {
            if (p < r.Begin)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator >(int p, RangeStruct r)
        {
            if (p > r.End)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator <(RangeStruct r, int p)
        {
            if (r.End < p)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator >(RangeStruct r, int p)
        {
            if (r.Begin > p)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static RangeStruct operator +(RangeStruct a, int b)
        {
            return new RangeStruct()
            {
                Begin = a.Begin + b,
                End = a.End + b
            };
        }
        public static RangeStruct operator -(RangeStruct a, int b)
        {
            return new RangeStruct()
            {
                Begin = a.Begin - b,
                End = a.End - b
            };
        }
        /// <summary>
        /// 向外扩大
        /// </summary>
        /// <param name="b"></param>
        /// <returns></returns>
        public RangeStruct ZoomIn(int b)
        {
            return new RangeStruct(Begin - b, End + b);
        }
        public RangeStruct ZoomIn(int b, int e)
        {
            return new RangeStruct(Begin - b, End + e);
        }

        /// <summary>
        /// 是否有交集
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool HasIntersection(RangeStruct r)
        {
            if (Contain(r.Begin))
                return true;

            if (Contain(r.End))
                return true;

            if (r.Contain(Begin))
                return true;

            if (r.Contain(End))
                return true;

            return false;
        }


        /// <summary>
        /// 可以合并
        /// </summary>
        /// <returns></returns>
        public bool CanUnion(RangeStruct r)
        {
            if (HasIntersection(r))
                return true;
            if (End == (r.Begin - 1))
                return true;
            if (Begin == (r.End + 1))
                return true;
            return false;
        }

        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (IsValid)
                return $"[{Begin},{End}]={Width}";
            else
                return "invalid";
        }
    }


    /// <summary>
    /// Range 比较器
    /// </summary>
    public class RangeStructEqualityComparer : IEqualityComparer<RangeStruct>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(RangeStruct x, RangeStruct y)
        {
            if ((x.Begin == y.Begin) && (x.End == y.End))
            {
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int GetHashCode(RangeStruct obj)
        {
            int hashCode = obj.Begin.GetHashCode();
            int hashCode2 = obj.End.GetHashCode();
            if (hashCode != hashCode2)
            {
                hashCode ^= hashCode2;
            }

            return hashCode;
        }
    }
    /// <summary>
    /// Range 辅助类
    /// </summary>
    public static class EListRangeStruct
    {
        /// <summary>
        /// rlist 必须是由小到大排列
        /// </summary>
        /// <param name="rlist"></param>
        /// <param name="r"></param>
        public static void Union(this List<RangeStruct> rlist, RangeStruct r)
        {
            for (int i = 0; i < rlist.Count(); i++)
            {
                RangeStruct r_dest = rlist[i];
                if (r < r_dest)//在 r_dest 前面
                {
                    rlist.Insert(i, r);
                    return;//完成
                }

                else if (r.CanUnion(r_dest)) //r 与 r_dest 有交集
                {
                    //r 与 r_dest 合体
                    r = r | r_dest;
                    rlist.RemoveAt(i);
                    i--;
                    //还需要继续判断
                }
            }
            //r 在 rlist 的后面
            rlist.Add(r);
        }


        /// <summary>
        /// 联合
        /// </summary>
        /// <param name="rlist1"></param>
        /// <param name="rlist2"></param>
        public static void Union(this List<RangeStruct> rlist1, List<RangeStruct> rlist2)
        {
            for (int i = 0; i < rlist2.Count(); i++)
            {
                rlist1.Union(rlist2[i]);
            }
        }
    }


}
