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

namespace Misc
{
    /// <summary>
    /// double范围类， 
    /// </summary>
    public class RangeF : INotifyPropertyChanged
    {
        #region property
        /// <summary>
        /// 开始
        /// </summary>
        public double Begin { get; set; }

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

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

        /// <summary>
        /// 本范围宽度
        /// </summary>
        [JsonIgnore]
        public double Width
        {
            get
            {
                if (IsValid)
                    return End - Begin;
                else
                    return double.NaN;
            }
        }


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

        /// <summary>
        /// 使用无效值初始化
        /// </summary>
        public RangeF()
        {
            Reset();
        }


        #region methods


        /// <summary>
        /// 范围 r 在 本范围内
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool Contain(RangeF 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(double p)
        {
            if ((Begin <= p) && (p <= End))
                return true;
            else
                return false;
        }



        /// <summary>
        /// 平移
        /// </summary>
        /// <param name="offset"></param>
        public void Move(double offset)
        {
            Begin += offset;
            End += offset;
        }


        /// <summary>
        /// 复位为无效
        /// </summary>
        public void Reset()
        {
            Begin = double.NaN;
            End = double.NaN;
        }


        /// <summary>
        /// 范围并集
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static RangeF operator |(RangeF a, RangeF b)
        {
            return new RangeF()
            {
                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 RangeF operator &(RangeF a, RangeF b)
        {
            RangeF r = new RangeF()
            {
                Begin = (a.Begin > b.Begin) ? a.Begin : b.Begin,
                End = (a.End < b.End) ? a.End : b.End
            };
            if (r.End < r.Begin)
            {
                return new RangeF();
            }
            else
            {
                return r;
            }
        }

        /// <summary>
        /// 范围 a小于b
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator <(RangeF a, RangeF 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 >(RangeF a, RangeF b)
        {
            if (b.End < (a.Begin))// [b.b,b.e][a.b,a.e]
            {
                return true;
            }
            else
            {
                return false;
            }
        }


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

        /// <summary>
        /// 是否有交集
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool HasIntersection(RangeF 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(RangeF r)
        {
            if (HasIntersection(r))
                return true;
            if (End == (r.Begin - 1))
                return true;
            if (Begin == (r.End + 1))
                return true;
            return false;
        }

        /// <summary>
        /// 复制 r 的值到 本范围内
        /// </summary>
        /// <param name="r"></param>
        public void Copy(RangeF r)
        {
            Begin = r.Begin;
            End = r.End;
        }
        /// <summary>
        /// 克隆
        /// </summary>
        /// <returns></returns>
        public RangeF Clone()
        {
            RangeF r = new RangeF();
            r.Copy(this);
            return r;
        }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "[" + Begin.ToString() + "," + End.ToString() + "]=" + Width.ToString();
        }
        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion


    }

    /// <summary>
    /// Range 比较器
    /// </summary>
    public class RangeFEqualityComparer : IEqualityComparer<RangeF>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Equals(RangeF x, RangeF 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(RangeF obj)
        {
            int hashCode = obj.Begin.GetHashCode();
            int hashCode2 = obj.End.GetHashCode();
            if (hashCode != hashCode2)
            {
                hashCode ^= hashCode2;
            }

            return hashCode;
        }
    }
    /// <summary>
    /// RangeF 辅助类
    /// </summary>
    public static class EListRangeF
    {
        /// <summary>
        /// rlist 必须是由小到大排列
        /// </summary>
        /// <param name="rlist"></param>
        /// <param name="r"></param>
        public static void Union(this List<RangeF> rlist, RangeF r)
        {
            for (int i = 0; i < rlist.Count(); i++)
            {
                RangeF 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<RangeF> rlist1, List<RangeF> rlist2)
        {
            for (int i = 0; i < rlist2.Count(); i++)
            {
                rlist1.Union(rlist2[i]);
            }
        }
    }
}
