using System;
using System.Collections.Generic;
using System.Linq;

using BS.Shared.DataContracts;

namespace BS.Shared.Services
{
    //public enum CostRateType
    //{
    //    HourlyRate,
    //    MinutesIntervall,
    //    RateFactor
    //}

    //public class CostRate
    //{
    //    private DateTime? mEndDate;

    //    private DateTime? mStartDate;

    //    public decimal? Amount { get; set; }

    //    public CostRateType CostRateType { get; set; }

    //    public DateTime? EndDate
    //    {
    //        get
    //        {
    //            return this.mEndDate;
    //        }

    //        set
    //        {
    //            this.mEndDate = value;
    //            if (this.mEndDate != null)
    //            {
    //                this.mEndDate = this.mEndDate.Value.Date;
    //            }
    //        }
    //    }

    //    public DateTime? StartDate
    //    {
    //        get
    //        {
    //            return this.mStartDate;
    //        }

    //        set
    //        {
    //            this.mStartDate = value;
    //            if (this.mStartDate != null)
    //            {
    //                this.mStartDate = this.mStartDate.Value.Date;
    //            }
    //        }
    //    }
    //}

    //public static class CostRateCalculationService
    //{
    //    public static CostRate GetActualCostRatePeriod(List<CostRate> costRates, CostRateType costRateType)
    //    {
    //        if (costRates != null)
    //        {
    //            foreach (CostRate crp in costRates)
    //            {
    //                if (crp.CostRateType == costRateType && crp.EndDate == null)
    //                {
    //                    return crp;
    //                }
    //            }
    //        }

    //        return null;
    //    }

    //    public static decimal GetActualHourlyRate(List<CostRate> costRates)
    //    {
    //        decimal val = 0;
    //        CostRate crp = GetActualCostRatePeriod(costRates, CostRateType.HourlyRate);
    //        if (crp != null && crp.Amount.HasValue)
    //        {
    //            val = crp.Amount.Value;
    //        }

    //        return val;
    //    }

    //    public static int GetActualMinuteInterval(List<CostRate> costRates)
    //    {
    //        int val = 1;
    //        CostRate crp = GetActualCostRatePeriod(costRates, CostRateType.MinutesIntervall);
    //        if (crp != null && crp.Amount.HasValue)
    //        {
    //            val = (int)crp.Amount.Value;
    //        }

    //        return val;
    //    }

    //    public static decimal GetActualRateFactor(List<CostRate> costRates)
    //    {
    //        decimal val = 0;
    //        CostRate crp = GetActualCostRatePeriod(costRates, CostRateType.RateFactor);
    //        if (crp != null && crp.Amount.HasValue)
    //        {
    //            val = crp.Amount.Value;
    //        }

    //        return val;
    //    }

        //public static decimal GetAmountTotal(CostBearer2SupportConceptData cb2sc)
        //{
        //    decimal total = 0;

        //    if (cb2sc != null && cb2sc.CostRateList != null)
        //    {
        //        decimal flsTotal = GetApprovedFLSTotal(cb2sc);

        //        if (cb2sc.ApprovedStartDate != null && cb2sc.ApprovedEndDate != null)
        //        {
        //            List<CostRate> list = cb2sc.CostRateList.Where(cr => cr.CostRateType == CostRateType.HourlyRate && cr.Amount != null).OrderBy(cr => cr.EndDate).ToList();

        //            DateTime lastStartDate = cb2sc.ApprovedStartDate.Value;

        //            if (list.Count > 1 && list[0].EndDate == null)
        //            {
        //                CostRate last = list[0];
        //                list.RemoveAt(0);
        //                list.Add(last);
        //            }

        //            foreach (var item in list)
        //            {
        //                decimal hourlyRate = 0;
        //                decimal rateFactor = 0;
        //                double flsInRange = 0;

        //                if (item.EndDate == null && lastStartDate <= cb2sc.ApprovedEndDate)
        //                {
        //                    hourlyRate = item.Amount.Value;
        //                    flsInRange = GetApprovedFLSInTimeSpan(cb2sc, lastStartDate, cb2sc.ApprovedEndDate.Value);
        //                }

        //                if (item.EndDate != null && item.EndDate >= cb2sc.ApprovedStartDate && item.EndDate <= cb2sc.ApprovedEndDate)
        //                {
        //                    hourlyRate = item.Amount.Value;
        //                    flsInRange = GetApprovedFLSInTimeSpan(cb2sc, lastStartDate, item.EndDate.Value);
        //                    lastStartDate = item.EndDate.Value;

        //                    if (lastStartDate < DateTime.MaxValue)
        //                    {
        //                        lastStartDate = lastStartDate.AddDays(1);
        //                    }
        //                }

        //                total += (decimal)flsInRange * hourlyRate;
        //            }
        //        }
        //    }

        //    return total;
        //}

        //public static double GetApprovedFLSInTimeSpan(CostBearer2SupportConceptData cb2sc, DateTime start, DateTime end)
        //{
        //    double flsApproved = 0;

        //    if (cb2sc != null && start != null && end != null && cb2sc.ApprovedEndDate != null && cb2sc.ApprovedStartDate != null)
        //    {
        //        decimal flsApprovedTotal = GetApprovedFLSTotal(cb2sc);
        //        TimeSpan durationTotal = cb2sc.ApprovedEndDate.Value.Subtract(cb2sc.ApprovedStartDate.Value);
        //        TimeSpan duration = end.Subtract(start);

        //        flsApproved = ((double)flsApprovedTotal * (duration.TotalDays + 1)) / (durationTotal.TotalDays + 1);
        //    }

        //    return flsApproved;
        //}

        //public static decimal GetApprovedFLSPerWeek(CostBearer2SupportConceptData cb2sc)
        //{
        //    decimal flsApproved = 0;

        //    if (cb2sc != null)
        //    {
        //        if (cb2sc.ApprovedFLS == null)
        //        {
        //            if (cb2sc.ApprovedFLSTotal != null && cb2sc.StartDate != null && cb2sc.EndDate != null)
        //            {
        //                decimal flsApprovedTotal = cb2sc.ApprovedFLSTotal.Value;
        //                decimal lDurationInWeeks = Convert.ToDecimal((cb2sc.EndDate.Value - cb2sc.StartDate.Value).Days + 1) / 7;
        //                flsApproved = flsApprovedTotal / lDurationInWeeks;
        //            }
        //        }
        //        else
        //        {
        //            flsApproved = cb2sc.ApprovedFLS.Value;
        //        }

        //        if (cb2sc.IsCalculatingWithFactor && flsApproved > 0)
        //        {
        //            decimal factor = GetActualRateFactor(cb2sc.CostRateList);
        //            if (factor > 0)
        //            {
        //                flsApproved = (flsApproved * 100) / (factor + 100);
        //            }
        //        }
        //    }

        //    return flsApproved;
        //}

        //public static decimal GetApprovedFLSTotal(CostBearer2SupportConceptData cb2sc)
        //{
        //    decimal flsApprovedTotal = 0;

        //    if (cb2sc != null)
        //    {
        //        if (cb2sc.ApprovedFLSTotal == null)
        //        {
        //            if (cb2sc.ApprovedFLS != null && cb2sc.StartDate != null && cb2sc.EndDate != null)
        //            {
        //                decimal flsApprovedPerWeek = cb2sc.ApprovedFLS.Value;
        //                decimal lDurationInWeeks = Convert.ToDecimal((cb2sc.EndDate.Value - cb2sc.StartDate.Value).Days + 1) / 7;
        //                flsApprovedTotal = flsApprovedPerWeek * lDurationInWeeks;
        //            }
        //        }
        //        else
        //        {
        //            flsApprovedTotal = cb2sc.ApprovedFLSTotal.Value;
        //        }

        //        if (cb2sc.IsCalculatingWithFactor && flsApprovedTotal > 0)
        //        {
        //            decimal factor = GetActualRateFactor(cb2sc.CostRateList);
        //            if (factor > 0)
        //            {
        //                flsApprovedTotal = (flsApprovedTotal * 100) / (factor + 100);
        //            }
        //        }
        //    }

        //    return flsApprovedTotal;
        //}

        // public static decimal GetAmountPerMonth(CostBearer2SupportConceptData cb2sc)
        // {
        // decimal amount = 0;

        // if (cb2sc != null)
        // {
        // if (cb2sc.MonthlyPayment == null)
        // {
        // decimal total = GetAmountTotal(cb2sc);

        // if (cb2sc.StartDate != null && cb2sc.EndDate != null)
        // {
        // DateTime dt1 = DateTime.Now;
        // DateTime dt2 = DateTime.Now.AddDays(1000);

        // TimeSpan t1 = dt1.Subtract(dt2);
        // TimeSpan t2 = dt2.Subtract(dt1);

        // int d1 = t1.Days;
        // double d12 = t1.TotalDays;
        // int d2 = t2.Days;
        // double d22 = t2.TotalDays;

        // decimal lDurationInMonths = Convert.ToDecimal((cb2sc.EndDate.Value - cb2sc.StartDate.Value).Days + 1) / (365m / 12m);
        // amount = total / lDurationInMonths;
        // }
        // }
        // else
        // {
        // amount = cb2sc.MonthlyPayment.Value;
        // }
        // }
        // return amount;
        // }

        public static List<CostRatePeriodInfo> GetCostRateInfosInSpan(List<CostRate> crList, DateTime startDate, DateTime endDate)
        {
            List<CostRatePeriodInfo> hourlyRateInfos = new List<CostRatePeriodInfo>();
            List<CostRatePeriodInfo> rateFactorInfos = new List<CostRatePeriodInfo>();
            List<CostRatePeriodInfo> allCostRateInfos = new List<CostRatePeriodInfo>();

            foreach (var crp in crList)
            {
                if (crp.CostRateType == CostRateType.HourlyRate || crp.CostRateType == CostRateType.RateFactor)
                {
                    CostRatePeriodInfo crInfo = new CostRatePeriodInfo();
                    if (crp.StartDate == null)
                    {
                        crInfo.StartDate = DateTime.MinValue;
                    }
                    else
                    {
                        crInfo.StartDate = crp.StartDate.Value;
                    }

                    if (crp.EndDate == null)
                    {
                        crInfo.EndDate = DateTime.MaxValue;
                    }
                    else
                    {
                        crInfo.EndDate = crp.EndDate.Value;
                    }

                    if (crp.Amount != null)
                    {
                        if (crp.CostRateType == CostRateType.HourlyRate)
                        {
                            crInfo.HourlyRate = crp.Amount.Value;
                        }
                        else
                        {
                            crInfo.RateFactor = crp.Amount.Value;
                        }
                    }

                    if (crp.CostRateType == CostRateType.HourlyRate)
                    {
                        hourlyRateInfos.Add(crInfo);
                    }
                    else
                    {
                        rateFactorInfos.Add(crInfo);
                    }
                }
            }

            hourlyRateInfos = hourlyRateInfos.OrderBy(hr => hr.EndDate).ToList();
            rateFactorInfos = rateFactorInfos.OrderBy(hr => hr.EndDate).ToList();

            int hrCount = 0;
            int rfCount = 0;

            CostRatePeriodInfo lastHourlyRateInfo = null;
            CostRatePeriodInfo lastRateFactorInfo = null;

            DateTime nextStartDate = DateTime.MinValue;

            while ((hrCount < hourlyRateInfos.Count) || (rfCount < rateFactorInfos.Count))
            {
                CostRatePeriodInfo newInfo = new CostRatePeriodInfo();
                if (hrCount < hourlyRateInfos.Count)
                {
                    lastHourlyRateInfo = hourlyRateInfos[hrCount];
                }

                if (rfCount < rateFactorInfos.Count)
                {
                    lastRateFactorInfo = rateFactorInfos[rfCount];
                }

                newInfo.StartDate = nextStartDate;

                if (lastHourlyRateInfo == null)
                {
                    lastHourlyRateInfo = new CostRatePeriodInfo();
                    lastHourlyRateInfo.EndDate = DateTime.MaxValue;
                    lastHourlyRateInfo.HourlyRate = 0;
                    lastHourlyRateInfo.RateFactor = 0;
                    lastHourlyRateInfo.StartDate = DateTime.MinValue;
                }

                if (lastRateFactorInfo == null)
                {
                    lastRateFactorInfo = new CostRatePeriodInfo();
                    lastRateFactorInfo.EndDate = DateTime.MaxValue;
                    lastRateFactorInfo.HourlyRate = 0;
                    lastRateFactorInfo.RateFactor = 0;
                    lastRateFactorInfo.StartDate = DateTime.MinValue;
                }

                if (lastHourlyRateInfo.EndDate < lastRateFactorInfo.EndDate)
                {
                    newInfo.EndDate = lastHourlyRateInfo.EndDate;
                }
                else
                {
                    newInfo.EndDate = lastRateFactorInfo.EndDate;
                }

                newInfo.HourlyRate = lastHourlyRateInfo.HourlyRate;
                newInfo.RateFactor = lastRateFactorInfo.RateFactor;

                if (lastHourlyRateInfo.EndDate < lastRateFactorInfo.EndDate)
                {
                    hrCount++;
                    nextStartDate = lastHourlyRateInfo.EndDate;
                }
                else if (lastHourlyRateInfo.EndDate > lastRateFactorInfo.EndDate)
                {
                    rfCount++;
                    nextStartDate = lastRateFactorInfo.EndDate;
                }
                else
                {
                    hrCount++;
                    rfCount++;
                    nextStartDate = lastHourlyRateInfo.EndDate;
                }

                if (nextStartDate < DateTime.MaxValue)
                {
                    nextStartDate = nextStartDate.AddDays(1);
                }

                allCostRateInfos.Add(newInfo);
            }

            List<CostRatePeriodInfo> costRateInfosInSpanList = new List<CostRatePeriodInfo>();

            foreach (var ci in allCostRateInfos)
            {
                if (ci.StartDate <= endDate.Date && ci.EndDate >= startDate.Date)
                {
                    costRateInfosInSpanList.Add(ci);
                }
            }

            return costRateInfosInSpanList;
        }

        //public static CostRate GetCostRatePeriodForDate(List<CostRate> costRates, CostRateType costRateType, DateTime dt)
        //{
        //    CostRate minCostRatePeriodGreaterThanGivenDate = null;
        //    CostRate actualCostRatePeriod = null;
        //    if (costRates != null)
        //    {
        //        foreach (CostRate crp in costRates)
        //        {
        //            if (crp.CostRateType == costRateType)
        //            {
        //                if (crp.EndDate == null)
        //                {
        //                    actualCostRatePeriod = crp;
        //                }
        //                else if (crp.EndDate.Value.AddDays(1) > dt)
        //                {
        //                    if (minCostRatePeriodGreaterThanGivenDate == null || crp.EndDate < minCostRatePeriodGreaterThanGivenDate.EndDate)
        //                    {
        //                        minCostRatePeriodGreaterThanGivenDate = crp;
        //                    }
        //                }
        //            }
        //        }
        //    }

        //    if (minCostRatePeriodGreaterThanGivenDate == null)
        //    {
        //        minCostRatePeriodGreaterThanGivenDate = actualCostRatePeriod;
        //    }

        //    return minCostRatePeriodGreaterThanGivenDate;
        //}

        //public static decimal GetHourlyRateForDate(List<CostRate> costRates, DateTime date)
        //{
        //    decimal val = 0;
        //    CostRate crp = GetCostRatePeriodForDate(costRates, CostRateType.HourlyRate, date);
        //    if (crp != null && crp.Amount.HasValue)
        //    {
        //        val = crp.Amount.Value;
        //    }

        //    return val;
        //}

        //public static int GetMinuteIntervalForDate(List<CostRate> costRates, DateTime date)
        //{
        //    int val = 1;
        //    CostRate crp = GetCostRatePeriodForDate(costRates, CostRateType.MinutesIntervall, date);
        //    if (crp != null && crp.Amount.HasValue)
        //    {
        //        val = (int)crp.Amount.Value;
        //    }

        //    return val;
        //}

        //public static decimal GetRateFactorForDate(List<CostRate> costRates, DateTime date)
        //{
        //    decimal val = 0;
        //    CostRate crp = GetCostRatePeriodForDate(costRates, CostRateType.RateFactor, date);
        //    if (crp != null && crp.Amount.HasValue)
        //    {
        //        val = crp.Amount.Value;
        //    }

        //    return val;
        //}



        //public static decimal GetAmountTotal(SupportConceptCostBearerRelDC cbRelDC)
        //{

        //}

        //public static decimal GetApprovedHoursTotal(SupportConceptCostBearerRelDC cbRelDC)
        //{

        //}

        //public static decimal GetApprovedHoursPerWeekAverage(SupportConceptCostBearerRelDC cbRelDC)
        //{

        //}

        //public static decimal GetApprovedHoursPerWeek(DateTime date, SupportConceptCostBearerRelDC cbRelDC)
        //{

        //}

        //#endregion

    }


