using System;
using BeWo.Report.ReportObjects;
using BeWo.Report;
using BeWo.Data.Entities;
using BeWo.Data.Access;
using System.Collections.Generic;
using BS.Shared.Core;
using BeWo.Service.ServiceImplementations;

namespace BeWo.AachenerVerein
{
	public partial class Mitarbeiterauswertung : DevExpress.XtraReports.UI.XtraReport, IBeWoReport<QueryRO>
	{
		private decimal maxWochenstunden = 39;

		public Mitarbeiterauswertung()
		{
			InitializeComponent();
		}

		public void SetReportDataSource(QueryRO pRO)
		{
			InitDataSource(pRO);
			this.bindingSource1.DataSource = pRO;
		}

		private void InitDataSource(QueryRO ro)
		{
			IList<Employee> employees = DAOFactory.GenericDAO.GetAllActiveAndArchived<Employee>();
			Dictionary<long, Employee> empDict = new Dictionary<long, Employee>();
			foreach (var item in employees)
			{
				//if (item.Oid.Value == 2) //###raus
				empDict.Add(item.Oid.Value, item);
			}
			DateTime monatsAnfang = DateTime.MinValue;

			decimal sollGesamt = 0;
			decimal relationGesamt = 0;
			decimal gesamtGesamt = 0;
			decimal flsSollGesamt = 0;
			decimal flsPlusMinusGesamt = 0;
			decimal flsIstGesamt = 0;

			long starttime = DateTime.Now.Ticks;
			foreach (BeWo.Report.ReportObjects.QueryRO.Row row in ro.Rows)
			{
				

				if (monatsAnfang == DateTime.MinValue)
				{
					monatsAnfang = DateTime.Parse(row.Field2.ToString());
				}
				DateTime berichtsAnfang = monatsAnfang;
				DateTime monatsEnde = monatsAnfang.AddMonths(1);
				DateTime berichtsEnde = monatsAnfang.AddMonths(1);

				long oid = 0;
				if (Int64.TryParse(row.Field1.ToString(), out oid))
				{
					if (empDict.ContainsKey(oid))
					{
						//long starttime = DateTime.Now.Ticks;

						Employee emp = empDict[oid];
						IList<AbsenceTime> absenceTimes = emp.AbsenceTimes;

						row.Field2 = emp.Person.LastName;
						row.Field3 = null;

						decimal flsIst = 0;
						decimal mittelbarIst = 0;
						decimal bu = 0;
						decimal flsSollGesamtS4 = 0;
						decimal? fehlZeitenS5 = null;
						decimal? urlaubS6 = null;
						decimal tatsaechlicheSollStdS7 = 0;
						decimal flsSollS8 = 0;
						int arbeitstage = 0;

						bool istMitMehrstunden = false;
						bool istHonorarkraft = false;

						Contract c = emp.GetValidContractForDate(monatsAnfang);
						if (c == null) // Kein Vertrag vom 1. gefunden, gucken, ob es einen gibt, der mitten im Monat beginnt.
						{
							var c2 = GetNextValidContractForDate(monatsAnfang, emp);
							if (c2 != null && c2.EntryDate.HasValue && c2.EntryDate.Value < monatsEnde)
								c = c2;
						}
						if (c != null)
						{
							if (c.EntryDate.HasValue && c.EntryDate > monatsAnfang)
							{
								berichtsAnfang = c.EntryDate.Value;
							}
							if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
							{
								berichtsEnde = c.ContractEndDate.Value.Date.AddDays(1);
							}
						}

						IList<ServiceRecord> records = DAOFactory.SearchDAO.FindServiceRecords(emp.Oid, null);
						records = AnalysisServiceImp.FilterActiveServiceRecords(records);

						while (berichtsAnfang < berichtsEnde)
						{
							arbeitstage = GetArbeitstageImBereich(berichtsAnfang, berichtsEnde);


							if (c != null)
							{
								if (c.WeeklyTotalHours.HasValue)
								{
									bu = c.WeeklyTotalHours.Value / maxWochenstunden;
								}

								EmploymentType et = c.EmploymentType;
								if (et != null)
								{
									if (et.Oid.Value == 19)
										istMitMehrstunden = true;
									else if (et.Oid.Value == 18)
										istHonorarkraft = true;
								}
								if (c.EntryDate >= monatsEnde)
									bu = 0;
							}
							else
							{
								row.Field20 = "NoContract";
							}



							DateTimeSpan span = new DateTimeSpan();
							span.StartDate = berichtsAnfang;
							span.EndDate = berichtsEnde;

							
							foreach (var item in records)
							{
								if (!IsServiceRecordFehlzeit(item) && !IsPause(item))
								{
									if (item.Start.Value >= berichtsAnfang && item.Start.Value < berichtsEnde)
									{
										if (item.ServiceDescription != null &&
											item.ServiceDescription.ServiceCategory != null &&
											item.ServiceDescription.ServiceCategory.IsBillable)
											flsIst += item.RoundedDuration;
										else
											mittelbarIst += item.RoundedDuration;
									}
								}
							}

							if (berichtsAnfang == monatsAnfang && berichtsEnde == monatsEnde)
							{
								var tagMaxSoll = maxWochenstunden/5;

							    decimal? specialStunden = GetSpecialStunden(emp, c);
							    if (specialStunden.HasValue)
							    {
                                    bu = specialStunden.Value / arbeitstage / tagMaxSoll;
                                }
								
							}


							var sollDieserVetragsAbschnitt = arbeitstage * (maxWochenstunden / 5) * bu;

							if (berichtsAnfang == monatsAnfang && berichtsEnde == monatsEnde)
							{
                                decimal? specialStunden = GetSpecialStunden(emp, c);
							    if (specialStunden.HasValue)
							    {
							        sollDieserVetragsAbschnitt = specialStunden.Value;

							    }
							}

							decimal tatsaechlicheSoll = sollDieserVetragsAbschnitt;

							var fehlZeiten = GetFehlzeiten(records, berichtsAnfang, berichtsEnde);
							if (fehlZeiten.HasValue)
							{
								if (!fehlZeitenS5.HasValue)
									fehlZeitenS5 = 0;
								fehlZeitenS5 += fehlZeiten;

								tatsaechlicheSoll -= fehlZeiten.Value;
							}
							
							var urlaub = GetUrlaubKrankheit(absenceTimes, berichtsAnfang, berichtsEnde);
							if (urlaub.HasValue)
							{
								if (!urlaubS6.HasValue)
									urlaubS6 = 0;
								urlaubS6 += urlaub;

								tatsaechlicheSoll -= (urlaub.Value * (maxWochenstunden / 5) * bu);
							}

							
							decimal flsSoll = tatsaechlicheSoll;
							if (c != null && c.WeeklyFLS.HasValue && c.WeeklyTotalHours.HasValue && c.WeeklyTotalHours.Value != 0)
								flsSoll = tatsaechlicheSoll * (c.WeeklyFLS.Value / c.WeeklyTotalHours.Value);

							flsSollS8 += flsSoll;
							flsSollGesamtS4 += sollDieserVetragsAbschnitt;
							tatsaechlicheSollStdS7 += tatsaechlicheSoll;

							berichtsAnfang = berichtsEnde;
							berichtsEnde = monatsEnde;
							c = GetNextValidContractForDate(berichtsAnfang, emp);

							if (c != null)
							{
								if (c.EntryDate.HasValue && c.EntryDate >= berichtsAnfang)
									berichtsAnfang = c.EntryDate.Value;
								if (c.ContractEndDate.HasValue && c.ContractEndDate < monatsEnde)
								{
									berichtsEnde = c.ContractEndDate.Value.Date.AddDays(1);
								}
							}
						}
						flsIst /= 60m;
						mittelbarIst /= 60m;
						row.Field6 = String.Format("{0:0.00}", flsIst);
						row.Field7 = String.Format("{0:0.00}", mittelbarIst);
						//Decimal.TryParse(row.Field6.ToString(), out flsIst);
						//Decimal.TryParse(row.Field7.ToString(), out mittelbarIst);

						row.Field3 = String.Format("{0:0.00}", bu);



						

						row.Field4 = String.Format("{0:0.00}", flsSollGesamtS4);
						row.Field5 = String.Format("{0:0.00}", fehlZeitenS5);
						row.Field6 = String.Format("{0:0.00}", urlaubS6);
						row.Field7 = String.Format("{0:0.00}", tatsaechlicheSollStdS7);

						
						

						row.Field8 = String.Format("{0:0.00}", flsSollS8);
						row.Field9 = String.Format("{0:0.00}", flsIst);
						row.Field10 = String.Format("{0:0.00}", flsIst - flsSollS8);
						row.Field11 = String.Format("{0:0.00}", flsIst + mittelbarIst);
						//if (flsIst + mittelbarIst > 0)
						//{
						//    row.Field12 = String.Format("{0:0.00}%  ", (flsIst / (flsIst + mittelbarIst)) * 100);
						//if (flsSollS8 != 0)
						//    row.Field12 += String.Format("{0:0.00}%", ((flsIst * (30m / 39m)) / flsSollS8) * 100);
						//else
						//    row.Field12 += "";
						if (flsIst + mittelbarIst != 0)
							row.Field12 += String.Format("{0:0.00}%", (flsIst / (flsIst + mittelbarIst)) * 100);
						else
							row.Field12 += "";

						//}

						decimal stundengesamt = flsIst + mittelbarIst;
						decimal? ueberstunden = stundengesamt - tatsaechlicheSollStdS7;
						decimal? ueberstundenVormonat;
						decimal? mehrstunden = null;
						decimal? mehrstundenVormonat = null;

						decimal alteAuszahlungen = 0;
						
						BerechneUeberstundenBis(emp, monatsAnfang, out ueberstundenVormonat, out mehrstundenVormonat, out alteAuszahlungen, records);
						
						if (istMitMehrstunden)
						{
							decimal maxMonat = arbeitstage * (maxWochenstunden / 5);
							if (fehlZeitenS5.HasValue)
								maxMonat -= fehlZeitenS5.Value;
							if (urlaubS6.HasValue)
								maxMonat -= (urlaubS6.Value * (maxWochenstunden / 5) * bu);
							if (stundengesamt > maxMonat)
							{
								ueberstunden = stundengesamt - maxMonat;
								mehrstunden = maxMonat - tatsaechlicheSollStdS7;
							}
							else
							{
								mehrstunden = ueberstunden;
								ueberstunden = null;

							}
						}


						decimal ausbezahlt = 0;
						decimal freizeit = 0;

						BerechneUeberstundenAuszahlung(emp, monatsAnfang, monatsEnde, out ausbezahlt, out freizeit);



						row.Field13 = String.Format("{0:0.00}", ueberstunden ?? 0);
						row.Field14 = String.Format("{0:0.00}", ueberstundenVormonat ?? 0);
						row.Field15 = String.Format("{0:0.00}", ((ueberstundenVormonat ?? 0) + (ueberstunden ?? 0)) - ausbezahlt - freizeit);
						row.Field19 = String.Format("{0:0.##}/{1:0.##}", ausbezahlt, alteAuszahlungen + freizeit + ausbezahlt);

						row.Field16 = String.Format("{0:0.00}", mehrstunden);
						row.Field17 = String.Format("{0:0.00}", mehrstundenVormonat);
						row.Field18 = String.Format("{0:0.00}", mehrstundenVormonat + mehrstunden);

						if (istHonorarkraft)
						{
							row.Field3 = "";
							row.Field4 = "";
							row.Field5 = "";
							row.Field6 = "";
							row.Field7 = "";
							row.Field8 = "";
							//row.Field9 = "";
							//row.Field10 = "";
							//row.Field11 = "";
							//row.Field12 = "";
							row.Field13 = "";
							row.Field14 = "";
							row.Field15 = "";
							row.Field16 = "";
							row.Field17 = "";
							row.Field18 = "";
						}


						sollGesamt += tatsaechlicheSollStdS7;
						flsSollGesamt += flsSollS8;
						flsIstGesamt += flsIst;
						flsPlusMinusGesamt += (flsIst - flsSollS8);
						gesamtGesamt += flsIst + mittelbarIst;


						//long endtime = DateTime.Now.Ticks;

						//long diff = endtime - starttime;
						//double secs = diff / (double)10000000;

						//row.Field15 = String.Format("{0:0.00}", secs); //###raus
					}
				}


			}
			double secs = GetRunTimeSecs(starttime);

			cellSollGesamt.Text = String.Format("{0:0.00}", sollGesamt); //7
			cellFLSSollGesamt.Text = String.Format("{0:0.00}", flsSollGesamt); //8
			cellFLSIstGesamt.Text = String.Format("{0:0.00}", flsIstGesamt); //9
			cellFLSPlusMinusGesamt.Text = String.Format("{0:0.00}", flsPlusMinusGesamt);//10
			cellGesamtGesamt.Text = String.Format("{0:0.00}", gesamtGesamt);//11


			if (flsSollGesamt != 0)
				cellRelationGesamt.Text += String.Format("{0:0.00}%", ((flsIstGesamt * (30m / 39m)) / flsSollGesamt) * 100m);
			else
				cellRelationGesamt.Text += "";


			lblMonat.Text = String.Format("{0:MMMM yy}", monatsAnfang);

		}

	    private decimal? GetSpecialStunden(Employee emp, Contract contract)
	    {
	        if (emp.Person.LastName.ToLower() == "radtke")
	        {
	            if (contract != null)
	            {
	                return contract.WeeklyTotalHours*4;
	            }
	        }
	        if (emp.Person.LastName.ToLower() == "terhaart")
	            return 50m;
	        if (emp.Person.LastName.ToLower() == "vossebrecher")
	            return 22.5m;

	        return null;
	    }

	    private double GetRunTimeSecs(long starttime)
		{
			long endtime = DateTime.Now.Ticks;

			long diff = endtime - starttime;
			double secs = diff / (double)10000000;

			return secs;
		}

		private void BerechneUeberstundenAuszahlung(Employee emp, DateTime start, DateTime ende, out decimal ausbezahlt, out decimal freizeit)
		{
			ausbezahlt = 0;
			freizeit = 0;


			if (emp.Overtimes != null)
			{
				foreach (var ot in emp.Overtimes)
				{
					if (ot.Date >= start && ot.Date < start.AddMonths(1))
					{
						if (ot.Auszahlungsart != null && !String.IsNullOrEmpty(ot.Auszahlungsart.Name)
							&& ot.Auszahlungsart.Name.ToLower().IndexOf("freizeit") >= 0)
						{
							//freizeit += ot.Betrag;
						}
						else
						{
							ausbezahlt += ot.Betrag;
						}
					}
				}
			}
		}



		private void BerechneUeberstundenBis(Employee emp, DateTime monat, out decimal? ueberstunden, out decimal? mehrstunden, out decimal alteAuszahlungen, IList<ServiceRecord> records)
		{
			ueberstunden = null;
			mehrstunden = null;
			alteAuszahlungen = 0;

			//IList<ServiceRecord> records = DAOFactory.SearchDAO.FindServiceRecords(emp.Oid, null);
			//records = AnalysisServiceImp.FilterActiveServiceRecords(records);

			//decimal minutenGesamt = 0;
			//decimal soll = 0;

			

			Contract c = emp.FirstContract;


			//decimal stundenAbwesend = 0;
			if (c != null)
			{
				DateTime start = c.EntryDate.HasValue ? c.EntryDate.Value : new DateTime(2011, 1, 1);

				Dictionary<String, IList<ServiceRecord>> srDict = CreateServiceRecordDictByDate(records);

				while (c != null && start < monat)
				{
					bool istMitMehrstunden = false;
					EmploymentType et = c.EmploymentType;
					if (et != null && et.Oid.Value == 19)
					{
						istMitMehrstunden = true;
					}

					DateTime contractEnd = c.ContractEndDate.HasValue ? c.ContractEndDate.Value : DateTime.MaxValue;
					decimal bu = 0;
					if (c.WeeklyTotalHours.HasValue)
					{
						bu = c.WeeklyTotalHours.Value / maxWochenstunden;
					}
					

					while (start < monat && start < contractEnd)
					{
						decimal minutenMonat = 0;
						DateTime ende = new DateTime(start.Year, start.Month, 1).AddMonths(1);
						if (contractEnd < DateTime.MaxValue && contractEnd.AddDays(1) < ende)
							ende = contractEnd.AddDays(1);

						String key = String.Format("{0:yyyyMM}", start);

						if (srDict.ContainsKey(key))
						{
							foreach (var item in srDict[key])
							{
								if (item.Start >= start && item.Start < ende)
								{
									minutenMonat += item.RoundedDuration;
								}

							}
						}
						//foreach (var item in records)
						//{
						//	if (!IsServiceRecordFehlzeit(item) && !IsPause(item))
						//	{
						//		if (item.Start.HasValue && item.Start >= start && item.Start < ende)
						//		{
						//			minutenMonat += item.RoundedDuration;
						//		}
						//	}
						//}

						int arbeitstage = GetArbeitstageImBereich(start, ende);

						var tagMaxSoll = maxWochenstunden / 5;

                        decimal? specialStunden = GetSpecialStunden(emp, c);
					    if (specialStunden.HasValue)
					    {
                            bu = specialStunden.Value / arbeitstage / tagMaxSoll;
                        }
					    
						decimal maxSollMonat = arbeitstage * (maxWochenstunden / 5);
						decimal sollMitarbeiter = maxSollMonat * bu;


					    if (specialStunden.HasValue)
					    {
                            sollMitarbeiter = specialStunden.Value;
                        }

					    
						decimal? urlaub = GetUrlaubKrankheit(emp.AbsenceTimes, start, ende);
						decimal? fehlzeit = GetFehlzeiten(records, start, ende);

						if (fehlzeit.HasValue)
						{
							sollMitarbeiter -= fehlzeit.Value;
							maxSollMonat -= fehlzeit.Value;
						}
						if (urlaub.HasValue)
						{
							sollMitarbeiter -= (urlaub.Value * (maxWochenstunden / 5) * bu);
							maxSollMonat -= (urlaub.Value * (maxWochenstunden / 5) * bu);
						}

						decimal stundenMonat = minutenMonat /= 60m;

						if (istMitMehrstunden)
						{
							if (!mehrstunden.HasValue)
								mehrstunden = 0;

							if (stundenMonat > maxSollMonat)
							{
								if (!ueberstunden.HasValue)
									ueberstunden = 0;
								ueberstunden += (stundenMonat - maxSollMonat);
								mehrstunden += (maxSollMonat - sollMitarbeiter);
							}
							else
							{
								mehrstunden += (stundenMonat - sollMitarbeiter);
							}
						}
						else
						{
							if (!ueberstunden.HasValue)
								ueberstunden = 0;
							ueberstunden += stundenMonat - sollMitarbeiter;
						}

						decimal ausbezahlt = 0;
						decimal freizeit = 0;
						BerechneUeberstundenAuszahlung(emp, start, ende, out ausbezahlt, out freizeit);
						ueberstunden -= ausbezahlt;
						ueberstunden -= freizeit;

						alteAuszahlungen += ausbezahlt;
						alteAuszahlungen += freizeit;

						start = ende;
					}
					if (start >= contractEnd)
					{
						c = GetNextValidContractForDate(start, emp);
						if (c != null && c.EntryDate.HasValue && c.EntryDate >= start)
							start = c.EntryDate.Value;
						else
						{
							start = start.AddMonths(1);
							c = GetNextValidContractForDate(start, emp);
							if (c != null && c.EntryDate.HasValue && c.EntryDate >= start)
								start = c.EntryDate.Value;
						}
					}
				}
			}
		}

		private Dictionary<string, IList<ServiceRecord>> CreateServiceRecordDictByDate(IList<ServiceRecord> records)
		{
			var dict = new Dictionary<string, IList<ServiceRecord>>();
			foreach (var item in records)
			{
				if (!IsServiceRecordFehlzeit(item) && !IsPause(item))
				{
					if (item.Start.HasValue)
					{
						String key = String.Format("{0:yyyyMM}", item.Start.Value);

						IList<ServiceRecord> list;
						if (!dict.ContainsKey(key))
						{
							list = new List<ServiceRecord>();
							dict.Add(key, list);
						}
						else
						{
							list = dict[key];
						}
						list.Add(item);
					}
				}
			}
			return dict;
		}

		public Contract GetNextValidContractForDate(DateTime dt, Employee emp)
		{
			Contract contractNextToStartDate = emp.GetValidContractForDate(dt);

			if (contractNextToStartDate == null)
			{
				DateTime minDate = DateTime.MinValue;
				DateTime maxDate = DateTime.MaxValue;

				foreach (var item in emp.Contracts)
				{
					if (item.EntryDate.HasValue && item.EntryDate.Value >= dt)
					{
						if (contractNextToStartDate == null || item.EntryDate.Value < contractNextToStartDate.EntryDate.Value)
						{
							contractNextToStartDate = item;
						}
					}


				}
			}
			return contractNextToStartDate;
		}

		private decimal? GetUrlaubKrankheit(IList<AbsenceTime> absenceTimes, DateTime start, DateTime ende)
		{
			decimal? tage = null;
			if (absenceTimes != null)
			{
				foreach (var item in absenceTimes)
				{
					//if (!String.IsNullOrEmpty(item.AbsenceReason.Description) && (item.AbsenceReason.Description.ToLower().IndexOf("urlaub") >= 0
					//                                                              || item.AbsenceReason.Description.ToLower().IndexOf("krank") >= 0))
					//{


					DateTimeSpan span = new DateTimeSpan();

					span.StartDate = start;

					if (item.Start.HasValue && item.Start.Value > span.StartDate)
					{
						span.StartDate = item.Start.Value;
					}
					span.EndDate = ende;
					if (item.End.HasValue && item.End.Value.Date.AddDays(1) < span.EndDate)
					{
						span.EndDate = item.End.Value.Date.AddDays(1);
					}
					if (span.EndDate >= start && span.StartDate < ende)
					{
						//if (item.AbsenceReason.)
						if (!tage.HasValue)
							tage = 0;

						tage += (decimal)span.GetTimeSpan().TotalHours;
					}
					//}
				}
			}
			if (tage.HasValue)
				tage /= 24;
			return tage;
		}

		//private decimal? GetFehlzeiten(IList<ServiceRecord> records, DateTime monat)
		//{
		//	decimal? stunden = null;
		//	decimal minuten = 0;
		//	if (records != null)
		//	{
		//		foreach (var item in records)
		//		{
		//			if (IsServiceRecordFehlzeit(item))
		//			{
		//				if (item.Start.Value >= monat && item.Start.Value < monat.AddMonths(1))
		//					minuten += item.RoundedDuration;
		//			}
		//		}
		//	}
		//	if (minuten != 0)
		//		stunden = minuten / 60;
		//	return stunden;
		//}

		private decimal? GetFehlzeiten(IList<ServiceRecord> records, DateTime start, DateTime ende)
		{
			decimal? stunden = null;
			decimal minuten = 0;
			if (records != null)
			{
				foreach (var item in records)
				{
					if (IsServiceRecordFehlzeit(item))
					{
						if (item.Start.Value >= start && item.Start.Value < ende)
							minuten += item.RoundedDuration;
					}
				}
			}
			if (minuten != 0)
				stunden = minuten / 60;
			return stunden;
		}
		
		private int GetArbeitstageImBereich(DateTime von, DateTime bis)
		{
			DateTime dt = DateTime.Now;

			DateTime start = von;
			DateTime end = bis;

			TimeSpan ts = end.Subtract(start);

			int maxDays = (int)ts.TotalDays;

			while (start < end)
			{
				if (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday)
				{
					maxDays--;
				}
				else
				{
					if (IstFeiertag(start))
						maxDays--;
				}
				start = start.AddDays(1);
			}
			return maxDays;

		}

		private bool IstFeiertag(DateTime start)
		{
			List<DateTime> feiertage = GetFeiertage(start.Year);

			foreach (var dateTime in feiertage)
			{
				if (start == dateTime)
					return true;
			}
			return false;
		}

		private List<DateTime> GetFeiertage(int year)
		{
			List<DateTime> list = new List<DateTime>();
			list.Add(new DateTime(year, 1, 1)); // "Neujahr"));
			//list.Add(new DateTime(year, 1, 6)); // , "Heilige Drei Könige"));
			list.Add(new DateTime(year, 5, 1)); // , "Tag der Arbeit"));
			//list.Add(new DateTime(year, 8, 15)); // , "Mariä Himmelfahrt"));
			list.Add(new DateTime(year, 10, 3)); // , "Tag der dt. Einheit"));
			//list.Add(new DateTime(year, 10, 31)); // , "Reformationstag"));
			list.Add(new DateTime(year, 11, 1)); // , "Allerheiligen "));
			list.Add(new DateTime(year, 12, 24)); // , "Heilig Abend"));
			list.Add(new DateTime(year, 12, 25)); // , "1. Weihnachtstag"));
			list.Add(new DateTime(year, 12, 26)); // , "2. Weihnachtstag"));

			if (year >= 2012) // Sonderregelung Aachener Verein
				list.Add(new DateTime(year, 12, 31)); // , "Sylvester"));

			DateTime osterSonntag = GetOsterSonntag(year);
			//list.Add(osterSonntag); // , "Ostersonntag"));
			//list.Add(osterSonntag.AddDays(-3)); // , "Gründonnerstag"));
			list.Add(osterSonntag.AddDays(-48)); // , "Rosenmontag"));
			list.Add(osterSonntag.AddDays(-2)); // , "Karfreitag"));
			list.Add(osterSonntag.AddDays(1)); // , "Ostermontag"));
			list.Add(osterSonntag.AddDays(39)); // , "Christi Himmelfahrt"));
			//list.Add(osterSonntag.AddDays(49)); // , "Pfingstsonntag"));
			list.Add(osterSonntag.AddDays(50)); // , "Pfingstmontag"));
			list.Add(osterSonntag.AddDays(60)); // , "Fronleichnam"));

			return list;
		}


		private DateTime GetOsterSonntag(int year)
		{

			int g, h, c, j, l, i;

			g = year % 19;
			c = year / 100;
			h = ((c - (c / 4)) - (((8 * c) + 13) / 25) + (19 * g) + 15) % 30;
			i = h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11));
			j = (year + (year / 4) + i + 2 - c + (c / 4)) % 7;

			l = i - j;
			int month = (int)(3 + ((l + 40) / 44));
			int day = (int)(l + 28 - 31 * (month / 4));

			return new DateTime(year, month, day);

		}

		private bool IsServiceRecordFehlzeit(ServiceRecord sr)
		{
			if (sr.ServiceDescription != null && sr.ServiceDescription.ServiceCategory != null && sr.ServiceDescription.ServiceCategory.Name.ToLower().IndexOf("fehlzeit") >= 0)
				return true;
			return false;
		}

		private bool IsPause(ServiceRecord sr)
		{
			if (sr.ServiceDescription != null && sr.ServiceDescription.ServiceCategory != null && sr.ServiceDescription.ServiceCategory.Name.ToLower().IndexOf("pause") >= 0)
				return true;
			return false;
		}
	}
}
