using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;

using BeWo.Core.Service;

using BS.Shared.DataContracts;
using BS.Shared.Services;

namespace BeWo.View.Report.MitarbeiterKoelnRing
{
    public enum FLSReportType
    {
        Employee,
        Customer,
        Costbearer,
        Team
    }

    public enum DateInterval
    {
        Second,
        Minute,
        Hour,
        Day,
        Week,
        Month,
        Quarter,
        Year
    }

    public class FLSOverviewGenerator
    {
        public static List<FLSOverviewRow> CreateFLSOverviewRows(List<FLSAnalysisRootDC> dcList, FLSOverviewConfig config)
        {
            List<FLSOverviewRow> rows = new List<FLSOverviewRow>();
            try
            {
                
                List<FLSAnalysisRootDC> sortedList;


                if (config.ReportType == FLSReportType.Employee)
                    sortedList = dcList.OrderBy(s => s.Employee.ToString()).ToList();
                else if (config.ReportType == FLSReportType.Customer)
                    sortedList = dcList.OrderBy(s => s.Customer.ToString()).ToList();
                else
                    sortedList = dcList;
                bool checkIfEmpty = sortedList.Count > 0;
                foreach (var dc in sortedList)
                {
                    FLSOverviewRow row = new FLSOverviewRow();
                    row.FLSAnalysisRootDC = dc;
                    row.DetailRows = CreateDetailRows(dc, config);
                    if (!checkIfEmpty || row.DetailRows.Count > 2)
                    {
                        rows.Add(row);
                    }
                    else if (config.ShowOnlyTotalRows && row.DetailRows.Count == 2)
                    {
                        double total;

                        if (Double.TryParse(row.DetailRows[1].RowTotalFLS, out total))
                        {
                            if (total > 0)
                                rows.Add(row);
                        }
                    }

                }
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace + "\n\nINNER:\n\n" + ex.InnerException);
            }
            return rows;
        }

        public static List<FLSOverviewDetailRow> CreateDetailRows(FLSAnalysisRootDC dc, FLSOverviewConfig config)
        {
            List<FLSOverviewDetailRow> result = new List<FLSOverviewDetailRow>();

            List<int> dates = new List<int>();
            List<FLSOverviewDateValue> dateHeader = new List<FLSOverviewDateValue>();

            TimeSpan timeSpan = config.EndDate.Subtract(config.StartDate);

            //DateTime startDate = config.StartDate;
            //DateTime endDate = config.EndDate;
            Dictionary<int, String> headerDict = new Dictionary<int, String>();
            Dictionary<int, String> headerLongDict = new Dictionary<int, String>();

            DateTime actualDate;
            if (timeSpan.TotalDays > 0)
            {
                switch (config.DateInterval)
                {
                    case DateInterval.Day:
                        int day = 0;
                        actualDate = config.StartDate;
                        while (actualDate <= config.EndDate) 
                        {
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedDayName(actualDate.DayOfWeek) + ", " + actualDate.Day + "." + actualDate.Month + ".";
                            dateHeader.Add(dv);
                            actualDate = actualDate.AddDays(1);
                            if (config.StartDate.Year != config.EndDate.Year) 
                                headerDict.Add(day, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                            else
                                headerDict.Add(day, dv.DateValueText);

                            
                            dates.Add(day++);
                        }
                        
                        break;
                    case DateInterval.Month:
                        int month = 0;
                        actualDate = config.StartDate;
                        int lastMonth = 0;
                        while (actualDate <= config.EndDate)
                        {
                            lastMonth = actualDate.Month;
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedMonthName(lastMonth);
                            dateHeader.Add(dv);
                            actualDate = actualDate.AddMonths(1);
                            if (config.StartDate.Year != config.EndDate.Year)
                                headerDict.Add(month, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                            else
                                headerDict.Add(month, dv.DateValueText);
                            headerLongDict.Add(month, DateTimeFormatInfo.CurrentInfo.GetMonthName(lastMonth));
                            dates.Add(month++); 
                        }
                        if (lastMonth > 0 && config.EndDate.Month != lastMonth)
                        {
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedMonthName(config.EndDate.Month);
                            dateHeader.Add(dv);
                            if (config.StartDate.Year != config.EndDate.Year)
                                headerDict.Add(month, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                            else
                                headerDict.Add(month, dv.DateValueText);
                            dates.Add(month);
                        }
                        break;
                    case DateInterval.Quarter:
                        int quarter = 0;
                        actualDate = config.StartDate;
                        int lastQuarter = 0;
                        while (actualDate <= config.EndDate)
                        {
                            lastQuarter = GetQuarter(actualDate);
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = lastQuarter + ". Quartal";
                            dateHeader.Add(dv);
                            actualDate = actualDate.AddMonths(3);
                            if (config.StartDate.Year != config.EndDate.Year)
                                headerDict.Add(quarter, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                            else
                                headerDict.Add(quarter, dv.DateValueText);
                            dates.Add(quarter++);
                        }
                        if (lastQuarter > 0 && GetQuarter(config.EndDate) != lastQuarter)
                        {
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = GetQuarter(config.EndDate) + ". Quartal";
                            dateHeader.Add(dv);
                            if (config.StartDate.Year != config.EndDate.Year)
                                headerDict.Add(quarter, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                            else
                                headerDict.Add(quarter, dv.DateValueText);
                            dates.Add(quarter);
                        }
                        break;
                    case DateInterval.Year:
                        int year = 0;
                        actualDate = config.StartDate;
                        while (actualDate.Year <= config.EndDate.Year)
                        {
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = actualDate.Year.ToString();
                            dateHeader.Add(dv);
                            actualDate = actualDate.AddYears(1);
                            headerDict.Add(year, dv.DateValueText);
                            dates.Add(year++);
                        }
                        break;
                    default: //default Week
                        int week = 0;
                        actualDate = config.StartDate;
                        int lastWeek = 0;
                        int currentWeek = 0;
                        while (actualDate <= config.EndDate)
                        {
                            currentWeek = GetKW(actualDate);
                            if (currentWeek != lastWeek)
                            {
                                lastWeek = currentWeek;
                                FLSOverviewDateValue dv = new FLSOverviewDateValue();
                                dv.DateValueText = lastWeek + ". KW";
                                dateHeader.Add(dv);
                                if (config.StartDate.Year != config.EndDate.Year)
                                    headerDict.Add(week, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                                else
                                    headerDict.Add(week, dv.DateValueText);
                                dates.Add(week++);
                            }
                            actualDate = actualDate.AddDays(1);
                        }
                        if (lastWeek > 0 && GetKW(config.EndDate) != lastWeek)
                        {
                            FLSOverviewDateValue dv = new FLSOverviewDateValue();
                            dv.DateValueText = GetKW(config.EndDate) + ". KW";
                            dateHeader.Add(dv);
                            if (config.StartDate.Year != config.EndDate.Year)
                                headerDict.Add(week, dv.DateValueText + " " + actualDate.Year.ToString().Substring(2));
                                else
                                    headerDict.Add(week, dv.DateValueText);
                            dates.Add(week);
                        }
                        break;
                }
            }

            

            
            FLSOverviewDetailRow headerRow = new FLSOverviewDetailRow(DetailRowTypes.Header);
            headerRow.ShowOnlyTotalRows = config.ShowOnlyTotalRows;
            headerRow.ShowServiceRecords = config.ShowServiceRecords;
            if (config.ReportType == FLSReportType.Employee)
            {
                headerRow.GroupName = "Klient/in";
                headerRow.Text1 = "Abteilung";
                headerRow.Text2 = "Status";
            }
            else if (config.ReportType == FLSReportType.Customer)
                headerRow.GroupName = "Mitarbeiter/in";
            else if (config.ReportType == FLSReportType.Costbearer)
                headerRow.GroupName = "Kostenträger";
            else
                headerRow.GroupName = "Team";

            headerRow.RowTotalFLS = "Summe";
            headerRow.DateValues = dateHeader;
            result.Add(headerRow);

            List<string> intervals = new List<string>();

            Dictionary<int, decimal> dateValueTotals = new Dictionary<int,decimal>();
            Dictionary<GroupValue, decimal> approvedFLSDict = new Dictionary<GroupValue, decimal>();
            Dictionary<GroupValue, Dictionary<int, decimal>> groupDateValues = new Dictionary<GroupValue, Dictionary<int, decimal>>();

            Dictionary<GroupValue, Dictionary<int, List<ServiceRecordFLSOverviewDC>>> groupServiceRecordLists = new Dictionary<GroupValue, Dictionary<int, List<ServiceRecordFLSOverviewDC>>>();
            decimal lastApprovedFLS = 0;
            //Dictionary<int, decimal> otherValues = null;
            Dictionary<long, long> selectedServiceCategories = new Dictionary<long, long>();
            foreach (var item in config.ServiceCategories)
	        {
                selectedServiceCategories.Add(item.ServiceCategoryOid.Value, item.ServiceCategoryOid.Value);
        		 
	        }
            if (dc.Groups == null)
                dc.Groups = new List<FLSAnalysisGroupDC>();
            foreach (FLSAnalysisGroupDC groupDC in dc.Groups)
            {
                if (groupDC.SupportConcepts == null)
                    groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                foreach (SupportConceptFLSOverviewDC scDC in groupDC.SupportConcepts)
                {
                    
                    foreach (ServiceRecordFLSOverviewDC srDC in scDC.ServiceRecords)
                    {
                        decimal approvedFLS = 0;

                        if (srDC.ServiceDescription != null && srDC.ServiceDescription.Category != null &&
                            selectedServiceCategories.ContainsKey(srDC.ServiceDescription.Category.ServiceCategoryOid.Value))
                        {
                            DateTime date = srDC.Start.Value;
                            if (date >= config.StartDate && date <= config.EndDate)
                            {
                                int key = 0;
                                Dictionary<int, decimal> dateValues = null;
                                Dictionary<int, List<ServiceRecordFLSOverviewDC>> serviceRecordLists = null;

                                GroupValue group = new GroupValue();
                                if (srDC.GroupOid != null)
                                {
                                    group.OID = -1;
                                    group.DisplayName = "Gruppenbuchungen";
                                }
                                else if (groupDC.Customer != null)
                                {
                                    group.OID = groupDC.Customer.CustomerOid;
                                    group.DisplayName = groupDC.Customer.ToString();
                                    if (groupDC.Customer.VarFieldValues != null)
                                    {
                                        if (groupDC.Customer.VarFieldValues.ContainsKey(2))
                                        {
                                            group.Text1 = groupDC.Customer.VarFieldValues[2];
                                        }
                                        if (groupDC.Customer.VarFieldValues.ContainsKey(4))
                                        {
                                            group.Text2 = groupDC.Customer.VarFieldValues[4];
                                        }
                                    }
                                }
                                else
                                {
                                    group.OID = 0;
                                    group.DisplayName = "Sonstiges";
                                }
                                    

                                if (groupDateValues.ContainsKey(group))
                                    dateValues = groupDateValues[group];
                                else
                                {
                                    dateValues = new Dictionary<int, decimal>();
                                    groupDateValues[group] = dateValues;
                                }

                                if (groupServiceRecordLists.ContainsKey(group))
                                    serviceRecordLists = groupServiceRecordLists[group];
                                else
                                {
                                    serviceRecordLists = new Dictionary<int, List<ServiceRecordFLSOverviewDC>>();
                                    groupServiceRecordLists[group] = serviceRecordLists;
                                }
                                var relDC = scDC.SupportConcept2CostBearer;
                                Calculations calc = null;
                                if (relDC != null)
                                {
                                    calc = Calculations.GetInstance(relDC.CostBearer.CostBearerID);
                                }
                                approvedFLS = 0;
                                switch (config.DateInterval)
                                {
                                    case DateInterval.Day:
                                        key = GetDayIndex(date, config.StartDate);
                                        //approvedFLS = SupportConceptService.GetApprovedFLSPerWeek(scDC.SupportConcept2CostBearer) / 7;
                                        if (calc != null)
                                            approvedFLS = calc.GetApprovedHoursPerDay(relDC, config.StartDate) ?? 0m;
                                        break;
                                    case DateInterval.Month:
                                        key = GetMonthIndex(date, config.StartDate);
                                        //approvedFLS = SupportConceptService.GetApprovedFLSPerWeek(scDC.SupportConcept2CostBearer) * (decimal)4.33;
                                        if (calc != null)
                                            approvedFLS = (calc.GetApprovedHoursPerWeek(relDC, config.StartDate) ?? 0m) * 4.33m;
                                        break;
                                    case DateInterval.Quarter:
                                        key = GetQuarterIndex(date, config.StartDate);
                                        //approvedFLS = SupportConceptService.GetApprovedFLSPerWeek(scDC.SupportConcept2CostBearer) / 13;
                                        if (calc != null)
                                            approvedFLS = (calc.GetApprovedHoursPerWeek(relDC, config.StartDate) ?? 0m) * 4.33m * 3m;
                                        break;
                                    case DateInterval.Year:
                                        key = GetYearIndex(date, config.StartDate, config.EndDate);
                                        //approvedFLS = SupportConceptService.GetApprovedFLSPerWeek(scDC.SupportConcept2CostBearer) * 52;
                                        if (calc != null)
                                            approvedFLS = (calc.GetApprovedHoursPerWeek(relDC, config.StartDate) ?? 0m) * 52m;
                                        break;
                                    default: //default Week
                                        key = GetWeekIndex(date, config.StartDate);
                                        //approvedFLS = SupportConceptService.GetApprovedFLSPerWeek(scDC.SupportConcept2CostBearer);
                                        if (calc != null)
                                            approvedFLS = calc.GetApprovedHoursPerWeek(relDC, config.StartDate) ?? 0m;
                                        break;
                                }
                                lastApprovedFLS = approvedFLS;
                                decimal fls = srDC.RoundedDuration;
                                decimal totalFls = fls;

                                if (dateValues.ContainsKey(key))
                                    fls += dateValues[key];
                                dateValues[key] = fls;

                                List<ServiceRecordFLSOverviewDC> serviceRecordList;
                                if (serviceRecordLists.ContainsKey(key))
                                {
                                    serviceRecordList= serviceRecordLists[key];
                                }
                                else
                                {
                                    serviceRecordList = new List<ServiceRecordFLSOverviewDC>();
                                    serviceRecordLists.Add(key, serviceRecordList);
                                }
                                serviceRecordList.Add(srDC);

                                dateValues[key] = fls;

                                if (dateValueTotals.ContainsKey(key))
                                    totalFls += dateValueTotals[key];
                                dateValueTotals[key] = totalFls;

                                
                                if (!approvedFLSDict.ContainsKey(group))
                                {
                                    approvedFLSDict[group] = approvedFLS;
                                }
                            
                            }
                        }
                    }
                }   
            }

            List<GroupValue> groupList = groupDateValues.Keys.OrderBy(gr => gr.DisplayName).ToList();
            FLSOverviewDetailRow otherDetailRow = null;
            FLSOverviewDetailRow groupDetailRow = null;

            if (!config.ShowOnlyTotalRows)
            {
                foreach (GroupValue group in groupList)
                {
                    FLSOverviewDetailRow detailRow = new FLSOverviewDetailRow(DetailRowTypes.Detail);
                    detailRow.ShowServiceRecords = config.ShowServiceRecords;
                    detailRow.ShowOnlyTotalRows = config.ShowOnlyTotalRows;
                    if (config.ReportType != FLSReportType.Costbearer && config.ReportType != FLSReportType.Team && approvedFLSDict.ContainsKey(group))
                    {
                        //detailRow.SollFLS = approvedFLSDict[group];
                    }

                    detailRow.GroupName = group.DisplayName;
                    detailRow.Text1 = group.Text1;
                    detailRow.Text2 = group.Text2;
                    //detailRow.RowTotalFLS = String.Format("{0:0.00}", sr.RoundedDuration);

                    List<FLSOverviewDateValue> newDateValues = new List<FLSOverviewDateValue>();
                    Dictionary<int, decimal> allDateValues = groupDateValues[group];

                    if (allDateValues == null)
                        allDateValues = new Dictionary<int, decimal>();


                    Dictionary<int, List<ServiceRecordFLSOverviewDC>> allServiceRecordLists = groupServiceRecordLists[group];
                    if (allServiceRecordLists == null)
                        allServiceRecordLists = new Dictionary<int, List<ServiceRecordFLSOverviewDC>>();

                    decimal totalVal = 0;
                    foreach (int dateKey in dates)
                    {
                        decimal dateVal = 0;
                        if (allDateValues.ContainsKey(dateKey))
                        {
                            dateVal = allDateValues[dateKey];
                        }
                        totalVal += dateVal;

                        List<ServiceRecordFLSOverviewDC> serviceRecordList = null;
                        if (allServiceRecordLists.ContainsKey(dateKey))
                        {
                            serviceRecordList = allServiceRecordLists[dateKey];
                        }


                        FLSOverviewDateValue dv = new FLSOverviewDateValue();
                        dv.DateValue = (double)dateVal;
                        dv.DateValueText = String.Format("{0:0.00}", dateVal / 60);
                        if (serviceRecordList != null)
                            dv.ServiceRecordList = serviceRecordList.OrderBy(sr => sr.Start).ToList();

                        if (headerDict.ContainsKey(dateKey))
                        {
                            dv.HeaderValue = headerDict[dateKey];
                        }
                        if (headerLongDict.ContainsKey(dateKey))
                        {
                            dv.HeaderLongValue = headerLongDict[dateKey];
                        }

                        newDateValues.Add(dv);
                    }
                    detailRow.DateValues = newDateValues;
                    detailRow.TotalFLM = totalVal;
                    detailRow.RowTotalFLS = String.Format("{0:0.00}", totalVal / 60);
                    if (group.OID > 0)
                        result.Add(detailRow);
                    else if (group.OID < 0)
                        groupDetailRow = detailRow;
                    else
                        otherDetailRow = detailRow;

                }
            }
            else if (config.ShowServiceRecords)
            {
                if (groupList.Count > 0)
                {
                    FLSOverviewDetailRow detailRow = new FLSOverviewDetailRow(DetailRowTypes.Detail);
                    detailRow.ShowServiceRecords = config.ShowServiceRecords;
                    detailRow.ShowOnlyTotalRows = config.ShowOnlyTotalRows;
                    detailRow.GroupName = "";

                    List<FLSOverviewDateValue> newDateValues = new List<FLSOverviewDateValue>();
                    Dictionary<int, FLSOverviewDateValue> newDateValuesByDateKey = new Dictionary<int, FLSOverviewDateValue>();
                    decimal totalVal = 0;


                    GroupValue gv = groupList[0];

                    foreach (int dateKey in dates)
                    {
                        FLSOverviewDateValue dv = new FLSOverviewDateValue();

                        if (headerDict.ContainsKey(dateKey))
                        {
                            dv.HeaderValue = headerDict[dateKey];
                        }
                        if (headerLongDict.ContainsKey(dateKey))
                        {
                            dv.HeaderLongValue = headerLongDict[dateKey];
                        }
                        newDateValuesByDateKey.Add(dateKey, dv);
                        newDateValues.Add(dv);
                    }



                    foreach (GroupValue group in groupList)
                    {
                        Dictionary<int, decimal> allDateValues = groupDateValues[group];

                        if (allDateValues == null)
                            allDateValues = new Dictionary<int, decimal>();


                        Dictionary<int, List<ServiceRecordFLSOverviewDC>> allServiceRecordLists = groupServiceRecordLists[group];
                        if (allServiceRecordLists == null)
                            allServiceRecordLists = new Dictionary<int, List<ServiceRecordFLSOverviewDC>>();


                        foreach (int dateKey in dates)
                        {
                            decimal dateVal = 0;
                            if (allDateValues.ContainsKey(dateKey))
                            {
                                dateVal = allDateValues[dateKey];
                            }
                            totalVal += dateVal;

                            List<ServiceRecordFLSOverviewDC> serviceRecordList = null;
                            if (allServiceRecordLists.ContainsKey(dateKey))
                            {
                                serviceRecordList = allServiceRecordLists[dateKey];

                                foreach (var sr in serviceRecordList)
                                {
                                    sr.GroupName = group.DisplayName;
                                }
                            }


                            FLSOverviewDateValue dv = newDateValuesByDateKey[dateKey];
                            dv.DateValue += (double)dateVal;

                            if (dv.ServiceRecordList == null)
                                dv.ServiceRecordList = new List<ServiceRecordFLSOverviewDC>();
                            if (serviceRecordList != null)
                                dv.ServiceRecordList.AddRange(serviceRecordList);
                        }

                    }
                    foreach (var item in newDateValues)
                    {
                        item.ServiceRecordList = item.ServiceRecordList.OrderBy(sr => sr.Start).ToList();
                        item.DateValue = item.DateValue;
                        item.DateValueText = String.Format("{0:0.00}", item.DateValue / 60);
                    }
                    detailRow.DateValues = newDateValues;
                    detailRow.TotalFLM = totalVal;
                    detailRow.RowTotalFLS = String.Format("{0:0.00}", totalVal / 60);

                    result.Add(detailRow);
                }
            }
            if (groupDetailRow != null)
            {
                result.Add(groupDetailRow);
            }
            if (otherDetailRow != null)
            {
                result.Add(otherDetailRow);
            }

            FLSOverviewDetailRow totalRow = new FLSOverviewDetailRow(DetailRowTypes.Total);
            totalRow.ShowServiceRecords = config.ShowServiceRecords;
            totalRow.ShowOnlyTotalRows = config.ShowOnlyTotalRows;
            
            if (config.ShowOnlyTotalRows)
                totalRow.GroupName = "Geleistete FLS";
            else
                totalRow.GroupName = "Summe";


            List<FLSOverviewDateValue> newTotalDateValues = new List<FLSOverviewDateValue>();
            decimal totalTotalVal = 0;
            foreach (int dateKey in dates)
            {
                decimal dateVal = 0;
                if (dateValueTotals.ContainsKey(dateKey))
                {
                    dateVal = dateValueTotals[dateKey];
                }
                
                totalTotalVal += dateVal;
                FLSOverviewDateValue dv = new FLSOverviewDateValue();
                dv.DateValueText = String.Format("{0:0.00}", dateVal / 60);
                if (headerDict.ContainsKey(dateKey))
                {
                    dv.HeaderValue = headerDict[dateKey];
                }
                if (headerLongDict.ContainsKey(dateKey))
                {
                    dv.HeaderLongValue = headerLongDict[dateKey];
                }
                newTotalDateValues.Add(dv);
            }
            totalRow.TotalFLM = totalTotalVal;
            totalRow.RowTotalFLS = String.Format("{0:0.00}", totalTotalVal / 60);
            totalRow.DateValues = newTotalDateValues;

            switch (config.DateInterval)
            {
                case DateInterval.Day:
                    totalRow.SollFLS = dc.SollFLSPerWeek / 7;
                    break;
                case DateInterval.Month:
                    totalRow.SollFLS = dc.SollFLSPerWeek * (decimal)4.33;
                    break;
                case DateInterval.Quarter:
                    totalRow.SollFLS = dc.SollFLSPerWeek / 13;
                    break;
                case DateInterval.Year:
                    totalRow.SollFLS = dc.SollFLSPerWeek * 52;
                    break;
                default: //default Week
                    totalRow.SollFLS = dc.SollFLSPerWeek;
                    break;
            }
            if (config.ReportType == FLSReportType.Customer)
                totalRow.SollFLS = lastApprovedFLS;
            result.Add(totalRow);
            return result;
        }

        private static int GetKW(DateTime actualDate)
        {
            System.Globalization.Calendar objCal = CultureInfo.CurrentCulture.Calendar;
            int weekofyear = objCal.GetWeekOfYear(actualDate, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

            return weekofyear;
        }

        private static int GetQuarter(DateTime actualDate)
        {
            int quarter = (int)Math.Ceiling((double)actualDate.Month / (double)3);
            
            return quarter;
        }

        private static int GetDayIndex(DateTime date, DateTime startDate)
        {
            int days = date.Subtract(startDate).Days;
            return days;
        }

        private static int GetWeekIndex(DateTime date, DateTime startDate)
        {
            int weekIndexActual = 0;
            int kw = GetKW(date);
            if (kw >= 52 && date.Month == 1)
            {
                weekIndexActual = ((date.Year - 1) * 100) + kw;
            }
            else
            {
                weekIndexActual = (date.Year * 100) + kw;
            }
            DateTime idxDate = startDate;

            int weekIndex = 0;

            kw = GetKW(idxDate);
            if (kw >= 52 && idxDate.Month == 1)
            {
                weekIndex = ((idxDate.Year - 1) * 100) + kw;
            }
            else
            {
                weekIndex = (idxDate.Year * 100) + kw;
            }

            
            int count = 0;
            int lastWeekIndex = 0;
            while (weekIndex < weekIndexActual)
            {
                if (weekIndex != lastWeekIndex)
                {
                    lastWeekIndex = weekIndex;
                    count++;
                }
                idxDate = idxDate.AddDays(1);
                kw = GetKW(idxDate);
                if (kw >= 52 && idxDate.Month == 1)
                {
                    weekIndex = ((idxDate.Year - 1) * 100) + kw;
                }
                else
                {
                    weekIndex = (idxDate.Year * 100) + kw;
                }
                
            }


            return count;
        }

        private static int GetMonthIndex(DateTime date, DateTime startDate)
        {
            int monthIndexActual = (date.Year * 100) + date.Month;

            DateTime idxDate = startDate;
            int monthIndex = (idxDate.Year * 100) + idxDate.Month;
            int count = 0;
            while (monthIndex < monthIndexActual)
            {
                idxDate = idxDate.AddMonths(1);
                monthIndex = (idxDate.Year * 100) + idxDate.Month;
                count++;
            }

            return count;
        }

        private static int GetQuarterIndex(DateTime date, DateTime startDate)
        {
            int qrtIndexActual = (date.Year * 100) + GetQuarter(date);

            DateTime idxDate = startDate;
            int qrtIndex = (idxDate.Year * 100) + GetQuarter(idxDate);
            int count = 0;
            while (qrtIndex < qrtIndexActual)
            {
                idxDate = idxDate.AddMonths(3);
                qrtIndex = (idxDate.Year * 100) + GetQuarter(idxDate);
                count++;
            }

            return count;
        }

        private static int GetYearIndex(DateTime date, DateTime startDate, DateTime endDate)
        {
            return date.Year - startDate.Year;
        }

        private class GroupValue
        {
            internal bool IsCustomer { get; set; }
            internal long OID { get; set; }
            internal String DisplayName { get; set; }
            internal String Text1 { get; set; }
            internal String Text2 { get; set; }
            
            public override int GetHashCode()
            {
                return (int)OID;
            }

            public override bool Equals(object obj)
            {
                GroupValue otherValue = obj as GroupValue;
                if (otherValue != null)
                {
                    return this.OID == otherValue.OID;
                }
                return false;
            }
        }
    }
}
