using System;
using System.Collections.Generic;
using System.Linq;
using BeWo.Data.Entities;
using BeWo.Report.ReportObjects;

using BS.Shared.Extensions;


namespace GerdasPflegedienst
{
	public class GerdasMitarbeiterstundenkontoBerechnung : MitarbeiterstundenkontoBerechnung
	{
	    public override bool AddServiceRecordToDuration(ServiceRecord item)
	    {
	        if (item.ServiceDescription != null && item.ServiceDescription.Name == "Pause")
	        {
	            return false;
	        }

	        return true;
        }

	    public override bool ShouldCreateDayDetails()
		{
			return true;
		}

        public override MitarbeiterstundenkontoRO.DayDetail CreateDayDetail(DateTime date, MitarbeiterstundenkontoRO.EmployeeDetail ed)
        {
            MitarbeiterstundenkontoRO.DayDetail dd = new MitarbeiterstundenkontoRO.DayDetail();
            dd.Date = date.Date;
            dd.NightStart = 20;
            dd.NightEnd = 6;
            dd.MaxHoursUntilBreak = 24;
            dd.BreakMinutes = 0;

            CalculateAbsenceTimesForDay(dd, ed);
            return dd;
        }

        public override IList<MitarbeiterstundenkontoRO.DayDetail> CreateDayDetails(DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<ServiceRecord> recordsAll)
        {

            Dictionary<int, MitarbeiterstundenkontoRO.DayDetail> dayToDetail = new Dictionary<int, MitarbeiterstundenkontoRO.DayDetail>();

            for (int i = berichtStart.Day; i <= berichtEnde.AddDays(-1).Day; i++)
            {
                MitarbeiterstundenkontoRO.DayDetail dd = CreateDayDetail(new DateTime(berichtStart.Year, berichtStart.Month, i), ed);
                dayToDetail.Add(i, dd);
            }

            foreach (var sr in recordsAll)
            {
                if (sr.Start.HasValue && sr.Start >= berichtStart && sr.Start < berichtEnde && sr.End.HasValue)
                {
                    var dd = dayToDetail[sr.Start.Value.Day];

                    if (!IsServiceRecordFehlzeit(sr) && AddServiceRecordToDuration(sr))
                    {
                        decimal duration = 0;
                        if (sr.GroupRoundedDuration.HasValue)
                        {
                            duration = sr.GroupRoundedDuration.Value;
                        }
                        else
                        {
                            duration = sr.RoundedDuration;
                        }

                        dd.MinutesTotal += duration;
                        if (dd.ServiceRecords == null)
                            dd.ServiceRecords = new List<ServiceRecord>();
                        dd.ServiceRecords.Add(sr);

                        CalculateSpecialHours(dd, sr, duration);
                    }
                    else
                    {
                        if (sr.ServiceDescription.Name == "Pause")
                        {
                            dd.BreakMinutes += (int)sr.DurationMinutes;
                        }
                    }
                }
            }

            //Berechne von bis Zeiten
            foreach (var ddKeyValue in dayToDetail)
            {
                var dd = ddKeyValue.Value;

                if (dd.ServiceRecords != null)
                {
                    var orderedList = dd.ServiceRecords.OrderBy(i => i.Start);

                    DateTime lastEnd = DateTime.MinValue;
                    var gapCount = -1;

                    foreach (var sr in orderedList)
                    {
                        decimal duration = 0;
                        if (sr.GroupRoundedDuration.HasValue)
                        {
                            duration = sr.GroupRoundedDuration.Value;
                        }
                        else
                        {
                            duration = sr.RoundedDuration;
                        }

                        DateTime dtEnd = sr.Start.Value.AddMinutes((double)duration);
                        if (sr.Start > lastEnd)
                        {
                            gapCount++;

                        }
                        if (dtEnd > lastEnd)
                        {
                            lastEnd = dtEnd;
                        }
                        if (gapCount == 0)
                        {
                            if (!dd.StartDateTime1.HasValue || sr.Start < dd.StartDateTime1)
                            {
                                dd.StartDateTime1 = sr.Start;
                            }
                            if (!dd.EndDateTime1.HasValue || dtEnd > dd.EndDateTime1)
                            {
                                dd.EndDateTime1 = dtEnd;
                            }
                        }
                        else if (gapCount == 1)
                        {
                            if (!dd.StartDateTime2.HasValue || sr.Start < dd.StartDateTime2)
                            {
                                dd.StartDateTime2 = sr.Start;
                            }
                            if (!dd.EndDateTime2.HasValue || dtEnd > dd.EndDateTime2)
                            {
                                dd.EndDateTime2 = dtEnd;
                            }
                        }
                        else if (gapCount == 2)
                        {
                            if (!dd.StartDateTime3.HasValue || sr.Start < dd.StartDateTime3)
                            {
                                dd.StartDateTime3 = sr.Start;
                            }
                            if (!dd.EndDateTime3.HasValue || dtEnd > dd.EndDateTime3)
                            {
                                dd.EndDateTime3 = dtEnd;
                            }
                        }
                        else
                        {
                            if (!dd.StartDateTime4.HasValue || sr.Start < dd.StartDateTime4)
                            {
                                dd.StartDateTime4 = sr.Start;
                            }
                            if (!dd.EndDateTime4.HasValue || dtEnd > dd.EndDateTime4)
                            {
                                dd.EndDateTime4 = dtEnd;
                            }
                        }
                    }
                }
            }
            

            return dayToDetail.Values.OrderBy(dd => dd.Date).ToList();
        }

	    public override decimal GetAdditionalHours(IList<MitarbeiterstundenkontoRO.DayDetail> days, DateTime berichtStart, DateTime berichtEnde, MitarbeiterstundenkontoRO.EmployeeDetail ed, IList<ServiceRecord> recordsAll)
	    {
	        return 0;
	    }
	}
}
