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 class Range : INotifyPropertyChanged, Misc.ISaveToXml
    {
        #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
        static Range()
        {
            Misc.SaveToXmlHepler.Regist(typeof(Range));
        }
        
        
        
        /// <summary>
        /// 使用无效值初始化
        /// </summary>
        public Range()
        {
            Reset();
        }


        #region methods


        /// <summary>
        /// 范围 r 在 本范围内
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool Contain(Range 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>
        /// <param name="offset"></param>
        public void Move(int offset)
        {
            Begin += offset;
            End += offset;
        }


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


        /// <summary>
        /// 转换为8个字节
        /// </summary>
        /// <returns></returns>
        public byte[] ToBytes()
        {
            List<byte> buf = new List<byte>();
            buf.AddRange(BitConverter.GetBytes(Begin));
            buf.AddRange(BitConverter.GetBytes(End));
            return buf.ToArray();
        }
        /// <summary>
        /// 8个字节转换
        /// </summary>
        /// <param name="value"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public bool TryParse(byte[] value, int offset)
        {
            if (value.Length - offset < 8)
                return false;

            Begin = BitConverter.ToInt32(value, offset + 0);
            End = BitConverter.ToInt32(value, offset + 4);
            return true;
        }

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

        /// <summary>
        /// 范围 a小于b
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator <(Range a, Range 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 >(Range a, Range 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, Range r)
        {
            if (p < r.Begin)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator >(int p, Range r)
        {
            if (p > r.End)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator <(Range r, int p)
        {
            if (r.End < p)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator >(Range r, int p)
        {
            if (r.Begin > p)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        /// <summary>
        /// 是否有交集
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public bool HasIntersection(Range 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(Range 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(Range r)
        {
            Begin = r.Begin;
            End = r.End;
        }
        /// <summary>
        /// 克隆
        /// </summary>
        /// <returns></returns>
        public Range Clone()
        {
            Range r = new Range();
            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


        #region ISaveToXml 成员

        public string[] GetSavePropertyNames()
        {
            return new string[]{
                    "Begin","End"
                };
        }

        #endregion


    }

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

            return hashCode;
        }
    }

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


}
