using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace LJLib.Method
{
    public static class SortedListEx
    {
        /// <summary>
        /// 在有序列表中查找最大的小于等于dt的值的位置
        /// </summary>
        /// <typeparam name="T">有序列类型</typeparam>
        /// <param name="sortedList">有序列表</param>
        /// <param name="dt">查询值</param>
        /// <returns>位置，找不到返回-1</returns>
        public static int GetFirstIndexBefore<T>(this IList<T> sortedList, T dt) where T : IComparable<T>
        {
            if (sortedList.Count > 0)
            {
                return sortedList.GetFirstIndexBefore(dt, 0, sortedList.Count - 1);
            }
            return -1;
        }

        private static int GetFirstIndexBefore<T>(this IList<T> sortedList, T dt, int min, int max) where T : IComparable<T>
        {
            Trace.Assert(min <= max, string.Format("min <= max不正确,min:{0},max:{1}", min, max));

            if (dt.CompareTo(sortedList[max]) >= 0)
            {
                return max;
            }

            if (dt.CompareTo(sortedList[min]) < 0)
            {
                return -1;
            }

            Trace.Assert(min < max, string.Format("min < max不正确,min:{0},max:{1}", min, max));

            int mid = (min + max - 1) / 2;

            if (dt.CompareTo(sortedList[mid]) >= 0)
            {
                return GetFirstIndexBefore(sortedList, dt, mid, max - 1);
            }
            return GetFirstIndexBefore(sortedList, dt, min, mid - 1);
        }

        /// <summary>
        /// 在有序列表中查找最小的大于等于dt的值的位置
        /// </summary>
        /// <typeparam name="T">有序列类型</typeparam>
        /// <param name="sortedList">有序列表</param>
        /// <param name="dt">查询值</param>
        /// <returns>位置，找不到返回-1</returns>
        public static int GetFirstIndexAfter<T>(this IList<T> sortedList, T dt) where T : IComparable<T>
        {
            if (sortedList.Count > 0)
            {
                return GetFirstIndexAfter(sortedList, dt, 0, sortedList.Count - 1);
            }
            return -1;
        }

        private static int GetFirstIndexAfter<T>(this IList<T> sortedList, T dt, int min, int max) where T : IComparable<T>
        {
            Trace.Assert(min <= max, string.Format("min <= max不正确,min:{0},max:{1}", min, max));
            if (dt.CompareTo(sortedList[min]) <= 0)
            {
                return min;
            }

            if (dt.CompareTo(sortedList[max]) > 0)
            {
                return -1;
            }
            Trace.Assert(min < max, string.Format("min < max不正确,min:{0},max:{1}", min, max));

            int mid = (min + 1 + max) / 2;

            if (dt.CompareTo(sortedList[mid]) <= 0)
            {
                return GetFirstIndexAfter(sortedList, dt, min + 1, mid);
            }
            return GetFirstIndexAfter(sortedList, dt, mid + 1, max);
        }

        public static double GetQty(this SortedList<DateTime, double> line, DateTime end, int first)
        {
            Trace.Assert(first >= 0 && first < line.Count, "first >= 0 && first < line.Count");
            Trace.Assert(end >= line.Keys[first], "end >= line.Keys[first]");

            if (first < 0 || first >= line.Count)
            {
                throw new ArgumentException("参数异常", "first");
            }

            if (end < line.Keys[first])
            {
                throw new ArgumentException("参数异常", "end");
            }

            if (first + 1 == line.Count)
            {
                return line.Values[first];
            }

            return (line.Values[first + 1] - line.Values[first]) *
                   (end - line.Keys[first]).TotalHours /
                   (line.Keys[first + 1] - line.Keys[first]).TotalHours
                   + line.Values[first];
        }
    }
}
