using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.Extensions;
using BS.Shared.Services;

namespace BeWo.FibMarburg.Calculation
{
	public class FibCalculations : Calculations
	{



		public override decimal? GetApprovedHoursForPeriod(SupportConceptApprovalPeriodDC scapDC, List<CostRatePeriodDC> costRatePeriods, DateTime? pStart,
			DateTime? pEnd)
		{
			if (!pStart.HasValue || !pEnd.HasValue)
			{
				return null;
			}
			if (scapDC.ApprovedBEInterval.HasValue && scapDC.ApprovedBEPerInterval.HasValue)
			{
				if (scapDC.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Monthly)
				{
					var months = GetTotalMonths(pStart.Value, pEnd.Value);
					return months * scapDC.ApprovedBEPerInterval.Value;
				}
			}

			var periodInDays = (pEnd.Value.Date - pStart.Value.Date).Days + 1;

			var approvedPerDay = this.GetApprovedHoursPerDay(scapDC, costRatePeriods);
			var total = approvedPerDay*periodInDays;

			if (scapDC.SupportConceptApprovalPeriodOid.HasValue &&
				scapDC.ApprovedBEInterval.HasValue && scapDC.ApprovedBEPerInterval.HasValue &&  scapDC.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Yearly)
			{
				var sc = DAOFactory.GenericDAO.LoadByID<SupportConceptApprovalPeriod>(scapDC.SupportConceptApprovalPeriodOid.Value);

				var absenceTimes = sc.CostBearer2SupportConcept.SupportConcept.Customer.AbsenceTimes;

				if (absenceTimes.Count > 0)
				{
					var absenceMonths = GetAbsenceMonths(absenceTimes, pStart.Value, pEnd.Value);

					if (absenceMonths > 0)
					{
						var monthlyValue = scapDC.ApprovedBEPerInterval.Value/12;
						total -= monthlyValue*absenceMonths;
					}
				}

			}
		
			
			return total;
		}

		private int GetAbsenceMonths(IList<AbsenceTime> absenceTimes, DateTime start, DateTime end)
		{
			var startMonth = new DateTime(start.Year, start.Month, 1);
			int months = 0;
			while (startMonth <= end)
			{
				if (HasAbsenceTimeInMonth(absenceTimes, startMonth))
				{
					months++;
				}
				startMonth = startMonth.AddMonths(1);
			}
			return months;
		}

		private bool HasAbsenceTimeInMonth(IList<AbsenceTime> absenceTimes, DateTime dateTime)
		{
			var start = new DateTime(dateTime.Year, dateTime.Month, 1);

			foreach (var at in absenceTimes)
			{
				if (at.Start.HasValue && at.Start < start.AddMonths(1))
				{
					if (!at.End.HasValue || at.End.Value >= start)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
}
