using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeWo.Service.Reporting;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.Services;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Plugins;

namespace DiakonieKKKleve.Reporting
{
	public class DkkkAnnualReportFactory : AnnualReportFactory
	{
		protected DateTime ReportStartDate { get; set; }
		protected DateTime ReportEndDate { get; set; }
		protected CostBearer CostBearer { get; set; }
		protected long? TeamOid { get; set; }
		protected long? CustomerCareTypeValueListEntryOid { get; set; }
		protected Dictionary<long, List<CostBearer2SupportConcept>> Cb2ScListPerCustomerOid { get; set; }
		protected Dictionary<long, Customer> CustomerByOid { get; set; }
		protected Dictionary<long, bool> LiegtImStichtagByCustomerOid { get; set; }
		protected Dictionary<long, bool> LiegtImStichtagByC2SOid { get; set; }

		protected DateTime Stichtag
		{
			get
			{
				return new DateTime(ReportStartDate.Year, 12, 31);
			}
		}

		public override List<AnnualReportDC> CreateAnnualReport(CostBearer cb, long? teamOid, long? customerCareTypeValueListEntryOid, DateTime reportStartDate,
															   DateTime reportEndDate)
		{
			ReportStartDate = reportStartDate;
			ReportEndDate = reportEndDate;
			CostBearer = cb;
			TeamOid = teamOid;
			CustomerCareTypeValueListEntryOid = customerCareTypeValueListEntryOid;
			Cb2ScListPerCustomerOid = new Dictionary<long, List<CostBearer2SupportConcept>>();
			CustomerByOid = new Dictionary<long, Customer>();
			LiegtImStichtagByC2SOid = new Dictionary<long, bool>();
			LiegtImStichtagByCustomerOid = new Dictionary<long, bool>();

			var reports = new List<AnnualReportDC>();


			//Dictionary<long, bool> customer2TerminationProcessed = new Dictionary<long, bool>();
			Dictionary<ValueListEntry, int> countPerTerminationReasonAll = new Dictionary<ValueListEntry, int>();
			Dictionary<ValueListEntry, int> countPerTerminationReasonMale = new Dictionary<ValueListEntry, int>();
			Dictionary<ValueListEntry, int> countPerTerminationReasonFemale = new Dictionary<ValueListEntry, int>();

			Dictionary<long, VarFieldDef> oid2VarfieldDef = new Dictionary<long, VarFieldDef>();

			//Dictionary<long, bool> customer2VarfieldProcessed = new Dictionary<long, bool>();
			Dictionary<String, int> countPerWohnformAll = new Dictionary<String, int>();
			Dictionary<String, int> countPerWohnformMale = new Dictionary<String, int>();
			Dictionary<String, int> countPerWohnformFemale = new Dictionary<String, int>();

			Dictionary<String, int> countPerCityAll = new Dictionary<String, int>();
			Dictionary<String, int> countPerCityMale = new Dictionary<String, int>();
			Dictionary<String, int> countPerCityFemale = new Dictionary<String, int>();

			Dictionary<String, int> countPerBehinderungsartAll = new Dictionary<String, int>();
			Dictionary<String, int> countPerBehinderungsartMale = new Dictionary<String, int>();
			Dictionary<String, int> countPerBehinderungsartFemale = new Dictionary<String, int>();

			Dictionary<VarFieldDef, int> countPerVarfielddef2All = new Dictionary<VarFieldDef, int>();
			Dictionary<VarFieldDef, int> countPerVarfielddef2Male = new Dictionary<VarFieldDef, int>();
			Dictionary<VarFieldDef, int> countPerVarfielddef2Female = new Dictionary<VarFieldDef, int>();

			Dictionary<int, int> year2NewSCCountAll = new Dictionary<int, int>();
			Dictionary<int, int> year2NewSCCountMale = new Dictionary<int, int>();
			Dictionary<int, int> year2NewSCCountFemale = new Dictionary<int, int>();

			
			Dictionary<long, decimal> customerOid2Hours = new Dictionary<long, decimal>();
			
			int gruppe0_18Alle = 0;
			int gruppe0_18M = 0;
			int gruppe0_18F = 0;

			int gruppe18_25Alle = 0;
			int gruppe18_25M = 0;
			int gruppe18_25F = 0;

			int gruppe26_39Alle = 0;
			int gruppe26_39M = 0;
			int gruppe26_39F = 0;

			int gruppe40_49Alle = 0;
			int gruppe40_49M = 0;
			int gruppe40_49F = 0;

			int gruppe50_59Alle = 0;
			int gruppe50_59M = 0;
			int gruppe50_59F = 0;

			int gruppeAb60Alle = 0;
			int gruppeAb60M = 0;
			int gruppeAb60F = 0;

			var varFieldDefs = DAOFactory.GenericDAO.GetAllActive<VarFieldDef>();
			foreach (var varFieldDef in varFieldDefs)
			{
				oid2VarfieldDef.Add(varFieldDef.Oid.Value, varFieldDef);
			}

			InitData();
			
			

			Dictionary<long, int> customerOid2Days = new Dictionary<long, int>();
			StringBuilder sb = new StringBuilder();
			foreach (var customerOid in Cb2ScListPerCustomerOid.Keys)
			{
				List<CostBearer2SupportConcept> csList = Cb2ScListPerCustomerOid[customerOid];
				
				Customer customer = CustomerByOid[customerOid];
				if (customerOid == 48)
				{
					int t = 0;
				}
				
				CostBearer2SupportConcept last = null;
				int days = 0;
				bool hatLaufendenHPAmStichtag = false;
				foreach (var c2s in csList)
				{
					var startdate = c2s.StartDate;
					if (last == null && customer.AssistanceBegin.HasValue && customer.AssistanceBegin.Value < startdate)
					{
						startdate = customer.AssistanceBegin;
					}

					DateTime enddate = DateTime.MaxValue;
					if (last != null && last.EndDate.Value.Date < DateTime.MaxValue.Date)
						enddate = last.EndDate.Value.Date.AddDays(1);
					bool isNewSc = !(last != null && (enddate == c2s.StartDate.Value.Date));
					
					
					if (last == null)
					{
						if (startdate.Value.Year == 2015)
						{
							sb.AppendLine(String.Format("{0}, {1}: {2:dd.MM.yyyy} - {3:dd.MM.yyyy} ({4:dd.MM.yyyy} - {5:dd.MM.yyyy})", customer.Person.LastName, customer.Person.FirstName, startdate, enddate, c2s.StartDate, c2s.EndDate));
							
						}
						days = 0;

						if (!year2NewSCCountAll.ContainsKey(startdate.Value.Year))
							year2NewSCCountAll[startdate.Value.Year] = 0;

						year2NewSCCountAll[startdate.Value.Year] += 1;

						if (!year2NewSCCountMale.ContainsKey(startdate.Value.Year))
							year2NewSCCountMale[startdate.Value.Year] = 0;
						if (!year2NewSCCountFemale.ContainsKey(startdate.Value.Year))
							year2NewSCCountFemale[startdate.Value.Year] = 0;

						if (c2s.SupportConcept.Customer.Person.Sex.HasValue && c2s.SupportConcept.Customer.Person.Sex.Value == Sex.Male)
						{
							year2NewSCCountMale[startdate.Value.Year] += 1;
						}
						if (c2s.SupportConcept.Customer.Person.Sex.HasValue && c2s.SupportConcept.Customer.Person.Sex.Value == Sex.Female)
						{
							year2NewSCCountFemale[startdate.Value.Year] += 1;
						}
					}

					if (LiegtImStichtagByC2SOid.ContainsKey(c2s.Oid.Value))
					{
						days += (int)Stichtag.Subtract(startdate.Value).TotalDays + 1;
						hatLaufendenHPAmStichtag = true;


						if (!customerOid2Hours.ContainsKey(customerOid))
							customerOid2Hours.Add(customerOid, 0);

						var calc = PluginLoader.FindClass<Calculations>(c2s.CostBearer.ID) ?? Calculations.GetInstance(c2s.CostBearer.ID);

						SupportConceptCostBearerRelDC relDC =
							MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
						decimal hours = calc.GetApprovedHoursPerWeek(relDC, reportEndDate.AddDays(-1)) ?? 0;

						customerOid2Hours[customerOid] += hours;
					}
					else
					{
						if (c2s.EndDate.Value < Stichtag)
							days += (int)c2s.EndDate.Value.Subtract(startdate.Value).TotalDays + 1;
					}


					last = c2s;
				}
				//if (!customerOid2Days.ContainsKey(customerOid))
				//    customerOid[customerOid]
				if (hatLaufendenHPAmStichtag)
				{
					customerOid2Days[customerOid] = days;
				}


				if (customer.TerminationReason != null && customer.TerminationDate.HasValue &&
					customer.TerminationDate >= reportStartDate && customer.TerminationDate < reportEndDate)
				{
					if (!countPerTerminationReasonAll.ContainsKey(customer.TerminationReason))
						countPerTerminationReasonAll[customer.TerminationReason] = 0;
					countPerTerminationReasonAll[customer.TerminationReason] += 1;

					if (!countPerTerminationReasonMale.ContainsKey(customer.TerminationReason))
						countPerTerminationReasonMale[customer.TerminationReason] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
					{
						countPerTerminationReasonMale[customer.TerminationReason] += 1;
					}

					if (!countPerTerminationReasonFemale.ContainsKey(customer.TerminationReason))
						countPerTerminationReasonFemale[customer.TerminationReason] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
					{
						countPerTerminationReasonFemale[customer.TerminationReason] += 1;
					}
				}

				if (customer.VarFieldValueList != null && customer.VarFieldValueList.Count > 0)
				{
					if (hatLaufendenHPAmStichtag)
					{
						foreach (var varfield in customer.VarFieldValueList)
						{
							if (oid2VarfieldDef.ContainsKey(varfield.VarFieldDefOid.Value))
							{
								VarFieldDef def = oid2VarfieldDef[varfield.VarFieldDefOid.Value];
								if (!String.IsNullOrEmpty(def.Label))
								{
									if (def.Label.Equals("Wohnform"))
									{
										Type type = Type.GetType(varfield.TypeName);
										var varFieldValue = Utils.XMLDeserializeFromString(varfield.SerializedValue, type);
										if (varFieldValue != null)
										{
											String str = varFieldValue.ToString();
											if (!countPerWohnformAll.ContainsKey(str))
												countPerWohnformAll[str] = 0;
											countPerWohnformAll[str] += 1;

											if (!countPerWohnformMale.ContainsKey(str))
												countPerWohnformMale[str] = 0;

											if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
											{
												countPerWohnformMale[str] += 1;
											}

											if (!countPerWohnformFemale.ContainsKey(str))
												countPerWohnformFemale[str] = 0;

											if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
											{
												countPerWohnformFemale[str] += 1;
											}
										}

									}
									else if (def.Label.IndexOf("Wohnraum") >= 0 &&
												def.Label.IndexOf("angemietet") >= 0)
									{
										if (!countPerVarfielddef2All.ContainsKey(def))
											countPerVarfielddef2All[def] = 0;
										countPerVarfielddef2All[def] += 1;

										if (!countPerVarfielddef2Male.ContainsKey(def))
											countPerVarfielddef2Male[def] = 0;

										if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
										{
											countPerVarfielddef2Male[def] += 1;
										}

										if (!countPerVarfielddef2Female.ContainsKey(def))
											countPerVarfielddef2Female[def] = 0;

										if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
										{
											countPerVarfielddef2Female[def] += 1;
										}
									}
								}
							}
							//if (varfield.)
						}

					}

				}

				

				if (hatLaufendenHPAmStichtag)
				{
					//Auswertung nach City
					String city = "Ohne Angabe";
					if (customer.Person.Address != null && !String.IsNullOrEmpty(customer.Person.Address.Town))
					{
						city = customer.Person.Address.Town;
					}
					if (!countPerCityAll.ContainsKey(city))
					{
						countPerCityAll[city] = 0;
					}
					countPerCityAll[city] += 1;

					if (!countPerCityMale.ContainsKey(city))
						countPerCityMale[city] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
					{
						countPerCityMale[city] += 1;
					}

					if (!countPerCityFemale.ContainsKey(city))
						countPerCityFemale[city] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
					{
						countPerCityFemale[city] += 1;
					}


					//Auswertung nach Behinderung
					String behinderung = GetBehinderungenList(customer);

					if (String.IsNullOrEmpty(behinderung))
					{
						behinderung = "Ohne Angabe";
					}

					if (!countPerBehinderungsartAll.ContainsKey(behinderung))
					{
						countPerBehinderungsartAll[behinderung] = 0;
					}
					countPerBehinderungsartAll[behinderung] += 1;

					if (!countPerBehinderungsartMale.ContainsKey(behinderung))
						countPerBehinderungsartMale[behinderung] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
					{
						countPerBehinderungsartMale[behinderung] += 1;
					}

					if (!countPerBehinderungsartFemale.ContainsKey(behinderung))
						countPerBehinderungsartFemale[behinderung] = 0;

					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
					{
						countPerBehinderungsartFemale[behinderung] += 1;
					}
				}
				ProcessCustomer(customer, csList);


				if (hatLaufendenHPAmStichtag)
				{
					if (customer.Person.DateOfBirth.HasValue)
					{
						int alter = Stichtag.Year - customer.Person.DateOfBirth.Value.Year;
						var dt = customer.Person.DateOfBirth.Value.AddYears(alter);
						if (Stichtag.CompareTo(dt) < 0)
						{
							alter--;
						}

						if (alter < 18)
						{
							gruppe0_18Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppe0_18M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppe0_18F++;
							}
						}
						if (alter >= 18 && alter <= 25)
						{
							gruppe18_25Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppe18_25M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppe18_25F++;
							}
						}
						if (alter >= 26 && alter <= 39)
						{
							gruppe26_39Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppe26_39M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppe26_39F++;
							}
						}
						if (alter >= 40 && alter <= 49)
						{
							gruppe40_49Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppe40_49M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppe40_49F++;
							}
						}
						if (alter >= 50 && alter <= 59)
						{
							gruppe50_59Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppe50_59M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppe50_59F++;
							}
						}
						if (alter >= 60)
						{
							gruppeAb60Alle++;
							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								gruppeAb60M++;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								gruppeAb60F++;
							}
						}
					}
				}
			}
			


			// anz Betreuungen
			AnnualReportDC report = CreateCountPerYearReport();
			reports.Add(report);

			// anz Zugänge
			report = new AnnualReportDC();
			report.Name = "Anzahl der Zugänge";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			var startYear = new DateTime(reportStartDate.Year - 5, 1, 1); //reportStartDate.AddYears(-1); //Vorjahr
			var index = 1;

			while (startYear < reportEndDate)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = String.Format("{0:yyyy}", new DateTime(startYear.Year, 1, 1));
				data.Value = 0;
				if (year2NewSCCountAll.ContainsKey(startYear.Year))
					data.Value = year2NewSCCountAll[startYear.Year];

				if (year2NewSCCountMale.ContainsKey(startYear.Year))
					data.Male = year2NewSCCountMale[startYear.Year];
				if (year2NewSCCountFemale.ContainsKey(startYear.Year))
					data.Female = year2NewSCCountFemale[startYear.Year];

				startYear = startYear.AddYears(1);
			}



			// anz Beendigungen
			report = new AnnualReportDC();
			report.Name = "Anzahl der Beendigungen der Betreuungen";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;

			foreach (var reason in countPerTerminationReasonAll.Keys)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = reason.Value;
				data.Value = countPerTerminationReasonAll[reason];

				if (countPerTerminationReasonMale.ContainsKey(reason))
					data.Male = countPerTerminationReasonMale[reason];
				if (countPerTerminationReasonFemale.ContainsKey(reason))
					data.Female = countPerTerminationReasonFemale[reason];

			}


			// Betreuungsdauer
			report = new AnnualReportDC();
			report.Name = "Aktuelle Betreuungsdauer der betreuten Personen";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;


			int below3All = 0;
			int three2FiveAll = 0;
			int above5All = 0;

			int below3Male = 0;
			int three2FiveMale = 0;
			int above5Male = 0;

			int below3Female = 0;
			int three2FiveFemale = 0;
			int above5Female = 0;

			foreach (var customerOid in customerOid2Days.Keys)
			{
				int days = customerOid2Days[customerOid];
				if (days > 0)
				{
					if (days < (365*3))
						below3All++;
					else if (days < (365*5))
						three2FiveAll++;
					else
					{
						above5All++;
					}

					if (CustomerByOid.ContainsKey(customerOid))
					{
						Customer customer = CustomerByOid[customerOid];
						if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
						{
							if (days < (365*3))
								below3Male++;
							else if (days < (365*5))
								three2FiveMale++;
							else
							{
								above5Male++;
							}
						}
						if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
						{
							if (days < (365*3))
								below3Female++;
							else if (days < (365*5))
								three2FiveFemale++;
							else
							{
								above5Female++;
							}
						}
					}
				}
			}
			AnnualReportDataDC d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "unter 3 Jahre";
			d.Value = below3All;
			d.Male = below3Male;
			d.Female = below3Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "3-5 Jahre";
			d.Value = three2FiveAll;
			d.Male = three2FiveMale;
			d.Female = three2FiveFemale;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "über 5 Jahre";
			d.Value = above5All;
			d.Male = above5Male;
			d.Female = above5Female;


			// Betreuungsumfang
			report = new AnnualReportDC();
			report.Name = "Betreuungsumfang der betreuten Personen in FLS pro Woche";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;


			
			int less1All = 0;
			int less1Male = 0;
			int less1Female = 0;
			int less2All = 0;
			int less2Male = 0;
			int less2Female = 0;
			int less3All = 0;
			int less3Male = 0;
			int less3Female = 0;
			int less4All = 0;
			int less4Male = 0;
			int less4Female = 0;
			int less6All = 0;
			int less6Male = 0;
			int less6Female = 0;
			int less8All = 0;
			int less8Male = 0;
			int less8Female = 0;
			int greater8All = 0;
			int greater8Male = 0;
			int greater8Female = 0;

			foreach (var customerOid in customerOid2Hours.Keys)
			{
				decimal hours = customerOid2Hours[customerOid];
				if (hours <= 1)
					less1All++;
				else if (hours <= 2)
					less2All++;
				else if (hours <= 3)
					less3All++;
				else if (hours <= 4)
					less4All++;
				else if (hours <= 6)
					less6All++;
				else if (hours <= 8)
					less8All++;
				else
					greater8All++;

				if (CustomerByOid.ContainsKey(customerOid))
				{
					Customer customer = CustomerByOid[customerOid];
					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
					{
						if (hours <= 1)
							less1Male++;
						else if (hours <= 2)
							less2Male++;
						else if (hours <= 3)
							less3Male++;
						else if (hours <= 4)
							less4Male++;
						else if (hours <= 6)
							less6Male++;
						else if (hours <= 8)
							less8Male++;
						else
							greater8Male++;
					}
					if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
					{
						if (hours <= 1)
							less1Female++;
						else if (hours <= 2)
							less2Female++;
						else if (hours <= 3)
							less3Female++;
						else if (hours <= 4)
							less4Female++;
						else if (hours <= 6)
							less6Female++;
						else if (hours <= 8)
							less8Female++;
						else
							greater8Female++;
					}
				}
			}
			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "<= 1 FLS";
			d.Value = less1All;
			d.Male = less1Male;
			d.Female = less1Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 1 <= 2 FLS";
			d.Value = less2All;
			d.Male = less2Male;
			d.Female = less2Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 2 <= 3 FLS";
			d.Value = less3All;
			d.Male = less3Male;
			d.Female = less3Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 3 <= 4 FLS";
			d.Value = less4All;
			d.Male = less4Male;
			d.Female = less4Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 4 <= 6 FLS";
			d.Value = less6All;
			d.Male = less6Male;
			d.Female = less6Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 6 <= 8 FLS";
			d.Value = less8All;
			d.Male = less8Male;
			d.Female = less8Female;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "> 8 FLS";
			d.Value = greater8All;
			d.Male = greater8Male;
			d.Female = greater8Female;

			// Nach Ort
			report = new AnnualReportDC();
			report.Name = "Anzahl der betreuten Personen nach Ort";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;

			foreach (var vd in countPerCityAll.Keys)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = vd;
				data.Value = countPerCityAll[vd];
				data.Male = countPerCityMale[vd];
				data.Female = countPerCityFemale[vd];
			}
			report.Data.Sort((a, b) => a.Name.CompareTo(b.Name));

			//Alter der betreuten Personen
			report = new AnnualReportDC();
			report.Name = "Alter der betreuten Personen";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "unter 18 Jahre";
			d.Value = gruppe0_18Alle;
			d.Male = gruppe0_18M;
			d.Female = gruppe0_18F;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "18 bis 25 Jahre";
			d.Value = gruppe18_25Alle;
			d.Male = gruppe18_25M;
			d.Female = gruppe18_25F;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "26 bis 39 Jahre";
			d.Value = gruppe26_39Alle;
			d.Male = gruppe26_39M;
			d.Female = gruppe26_39F;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "40 bis 49 Jahre";
			d.Value = gruppe40_49Alle;
			d.Male = gruppe40_49M;
			d.Female = gruppe40_49F;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "50 bis 59 Jahre";
			d.Value = gruppe50_59Alle;
			d.Male = gruppe50_59M;
			d.Female = gruppe50_59F;

			d = new AnnualReportDataDC();
			report.Data.Add(d);
			d.Index = index++;
			d.Name = "über 60 Jahre";
			d.Value = gruppeAb60Alle;
			d.Male = gruppeAb60M;
			d.Female = gruppeAb60F;

			// Nach Behinderung
			report = new AnnualReportDC();
			report.Name = "Behinderungsarten";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;

			foreach (var vd in countPerBehinderungsartAll.Keys)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = vd;
				data.Value = countPerBehinderungsartAll[vd];
				data.Male = countPerBehinderungsartMale[vd];
				data.Female = countPerBehinderungsartFemale[vd];
			}
			report.Data.Sort((a, b) => a.Name.CompareTo(b.Name));

			// anz der betreuten Personen
			report = new AnnualReportDC();
			report.Name = "Anzahl der betreuten Personen nach Wohnform";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;


			foreach (var wohnform in countPerWohnformAll.Keys)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = wohnform;
				data.Value = countPerWohnformAll[wohnform];
				data.Male = countPerWohnformMale[wohnform];
				data.Female = countPerWohnformFemale[wohnform];
			}

			// Wohnraum vom Leistungserbringer/Kooperationspartner des Leistungserbringers angemietet
			report = new AnnualReportDC();
			report.Name = "Wohnraum vom Leistungserbringer/Kooperationspartner angemietet";
			reports.Add(report);
			report.Data = new List<AnnualReportDataDC>();
			index = 1;

			foreach (var vd in countPerVarfielddef2All.Keys)
			{
				AnnualReportDataDC data = new AnnualReportDataDC();
				report.Data.Add(data);
				data.Index = index++;
				data.Name = "anz";
				data.Value = countPerVarfielddef2All[vd];
				data.Male = countPerVarfielddef2Male[vd];
				data.Female = countPerVarfielddef2Female[vd];
			}
			return reports;
		}

		public virtual void InitData()
		{
			foreach (var iCb2Sc in DAOFactory.GenericDAO.GetAllActiveAndArchived<CostBearer2SupportConcept>())
			{
				if (CostBearer == null || iCb2Sc.CostBearer.Oid == CostBearer.Oid)
				{
					var sc = iCb2Sc.SupportConcept;
					var customer = sc.Customer;
					if (customer.Oid.Value == 104)
					{
						int test = 0;
					}
					if (ShouldProcessSupportConcept(iCb2Sc, sc, customer))
					{
						ProcessSupportConcept(iCb2Sc, sc, customer);
						if (!CustomerByOid.ContainsKey(customer.Oid.Value))
						{
							CustomerByOid.Add(customer.Oid.Value, customer);
						}

						List<CostBearer2SupportConcept> list;
						if (Cb2ScListPerCustomerOid.ContainsKey(customer.Oid.Value))
						{
							list = Cb2ScListPerCustomerOid[customer.Oid.Value];
						}
						else
						{
							list = new List<CostBearer2SupportConcept>();
							Cb2ScListPerCustomerOid.Add(customer.Oid.Value, list);
						}
						//if (iCb2Sc.StartDate < ReportEndDate)
						//{
							list.Add(iCb2Sc);
							list.Sort((a, b) => a.StartDate.Value.CompareTo(b.StartDate.Value));
						//}
						
					}
				}
			}

			foreach (var customerOid in Cb2ScListPerCustomerOid.Keys)
			{
				if (customerOid == 104)
				{
					int test = 0;
				}
				var customer = CustomerByOid[customerOid];
				var c2sList = Cb2ScListPerCustomerOid[customerOid];

				bool isFirst = true;
				foreach (var c2s in c2sList)
				{

					var startDate = c2s.StartDate;
					if (isFirst && customer.AssistanceBegin.HasValue && customer.AssistanceBegin < startDate)
					{
						startDate = customer.AssistanceBegin;
					}
					isFirst = false;

					var endDate = c2s.EndDate;
					if (customer.TerminationDate.HasValue && customer.TerminationDate < endDate)
					{
						endDate = customer.TerminationDate;
					}


					if (startDate <= Stichtag && endDate >= Stichtag)
					{
						if (!LiegtImStichtagByCustomerOid.ContainsKey(customer.Oid.Value))
						{
							LiegtImStichtagByCustomerOid.Add(customer.Oid.Value, true);
						}
						if (!LiegtImStichtagByC2SOid.ContainsKey(c2s.Oid.Value))
						{
							LiegtImStichtagByC2SOid.Add(c2s.Oid.Value, true);
						}
					}
				}
			}
		}

		public virtual AnnualReportDC CreateCountPerYearReport()
		{
			var countPerYearEndAll = new Dictionary<int, int>();
			var countPerYearEndMale = new Dictionary<int, int>();
			var countPerYearEndFemale = new Dictionary<int, int>();

			var countPerYearMidAll = new Dictionary<int, int>();
			var countPerYearMidMale = new Dictionary<int, int>();
			var countPerYearMidFemale = new Dictionary<int, int>();

			countPerYearMidAll.Add(ReportStartDate.Year, 0);
			countPerYearMidAll.Add(ReportStartDate.Year - 1, 0);
			countPerYearMidAll.Add(ReportStartDate.Year - 2, 0);

			countPerYearMidMale.Add(ReportStartDate.Year, 0);
			countPerYearMidMale.Add(ReportStartDate.Year - 1, 0);
			countPerYearMidMale.Add(ReportStartDate.Year - 2, 0);

			countPerYearMidFemale.Add(ReportStartDate.Year, 0);
			countPerYearMidFemale.Add(ReportStartDate.Year - 1, 0);
			countPerYearMidFemale.Add(ReportStartDate.Year - 2, 0);

			countPerYearEndAll.Add(ReportStartDate.Year, 0);
			countPerYearEndAll.Add(ReportStartDate.Year - 1, 0);
			countPerYearEndAll.Add(ReportStartDate.Year - 2, 0);

			countPerYearEndMale.Add(ReportStartDate.Year, 0);
			countPerYearEndMale.Add(ReportStartDate.Year - 1, 0);
			countPerYearEndMale.Add(ReportStartDate.Year - 2, 0);

			countPerYearEndFemale.Add(ReportStartDate.Year, 0);
			countPerYearEndFemale.Add(ReportStartDate.Year - 1, 0);
			countPerYearEndFemale.Add(ReportStartDate.Year - 2, 0);

			var customerProcessed = new Dictionary<String, bool>();

			foreach (var customerOid in Cb2ScListPerCustomerOid.Keys)
			{
				if (customerOid == 104)
				{
					int test = 0;
				}

				var customer = CustomerByOid[customerOid];
				var c2sList = Cb2ScListPerCustomerOid[customerOid];

				for (int i = ReportStartDate.Year - 2; i <= ReportStartDate.Year; i++)
				{
					DateTime midYear = new DateTime(i, 6, 30);
					DateTime endYear = new DateTime(i, 12, 31);


					bool countedMid = false;
					bool countedEnd = false;

					bool isFirst = true;
					foreach (var c2s in c2sList)
					{
						
						var startDate = c2s.StartDate;
						if (isFirst && customer.AssistanceBegin.HasValue && customer.AssistanceBegin < startDate)
						{
							startDate = customer.AssistanceBegin;
						}
						isFirst = false;

						var endDate = c2s.EndDate;
						if (customer.TerminationDate.HasValue && customer.TerminationDate < endDate)
						{
							endDate = customer.TerminationDate;
						}
						if (!countedEnd && startDate <= endYear && endDate >= endYear)
						{
							countPerYearEndAll[i] += 1;

							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								countPerYearEndMale[i] += 1;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								countPerYearEndFemale[i] += 1;
							}
							countedEnd = true;
						}
						if (!countedMid && startDate <= midYear && endDate >= midYear)
						{
							countPerYearMidAll[i] += 1;

							if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Male)
							{
								countPerYearMidMale[i] += 1;
							}
							else if (customer.Person.Sex.HasValue && customer.Person.Sex.Value == Sex.Female)
							{
								countPerYearMidFemale[i] += 1;
							}
							countedMid = true;
						}
					}
					
				}
				
			}

			var report = new AnnualReportDC();
			report.Name = "Anzahl der Betreuungen";
			
			report.Data = new List<AnnualReportDataDC>();
			DateTime startYear = new DateTime(2000, 1, 1); //reportStartDate.AddYears(-1); //Vorjahr
			int index = 1;
			while (startYear < ReportEndDate)
			{
				if (countPerYearMidAll.ContainsKey(startYear.Year))
				{
					AnnualReportDataDC data = new AnnualReportDataDC();
					report.Data.Add(data);
					data.Index = index++;
					data.Name = String.Format("{0:dd/MM/yyyy}", new DateTime(startYear.Year, 6, 30));
					data.Value = countPerYearMidAll[startYear.Year];

					if (countPerYearMidMale.ContainsKey(startYear.Year))
					{
						data.Male = countPerYearMidMale[startYear.Year];
					}
					if (countPerYearMidFemale.ContainsKey(startYear.Year))
					{
						data.Female = countPerYearMidFemale[startYear.Year];
					}

				}
				if (countPerYearEndAll.ContainsKey(startYear.Year))
				{
					AnnualReportDataDC data = new AnnualReportDataDC();
					report.Data.Add(data);
					data.Index = index++;
					data.Name = String.Format("{0:dd/MM/yyyy}", new DateTime(startYear.Year, 12, 31));
					data.Value = countPerYearEndAll[startYear.Year];

					if (countPerYearEndMale.ContainsKey(startYear.Year))
					{
						data.Male = countPerYearEndMale[startYear.Year];
					}
					if (countPerYearEndFemale.ContainsKey(startYear.Year))
					{
						data.Female = countPerYearEndFemale[startYear.Year];
					}
				}

				startYear = startYear.AddYears(1);
			}

			return report;
		}

		public virtual void ProcessCustomer(Customer customer, List<CostBearer2SupportConcept> allCostBearer2SupportConcepts)
		{
			//Nur für abgeleitete Klassen
		}

		public virtual void ProcessSupportConcept(CostBearer2SupportConcept iCb2Sc, SupportConcept sc, Customer customer)
		{
			//Nur für abgeleitete Klassen
		}

		public virtual bool ShouldProcessSupportConcept(CostBearer2SupportConcept iCb2Sc, SupportConcept sc, Customer customer)
		{

			if (sc.IsActive != ActivationTypeId.Deleted && customer.IsActive != ActivationTypeId.Deleted)
			{
				if ((iCb2Sc.ApprovedStartDate.HasValue && iCb2Sc.ApprovedEndDate.HasValue) ||
				    (iCb2Sc.RequestedEndDate.HasValue && iCb2Sc.RequestedEndDate >= DateTime.Now.Date))
				{
					if (CustomerBelongsToTeam(customer, TeamOid) &&
					    IsCustomerOfCustomerCareType(customer, CustomerCareTypeValueListEntryOid))
					{
						return true;
					}
				}
			}
			return false;
		}

		public virtual bool IsCustomerOfCustomerCareType(Customer customer, long? customerCareTypeValueListEntryOid)
		{
			bool val = true;
			if (customerCareTypeValueListEntryOid.HasValue)
			{
				val = false;
				foreach (var v in customer.ValueList)
				{
					if (v.Entry.Type == ValueListEntryType.CustomerCareType && v.Entry.Oid == customerCareTypeValueListEntryOid)
						return true;
				}
			}
			return val;
		}

		public virtual bool CustomerBelongsToTeam(Customer customer, long? teamOid)
		{
			bool val = true;
			if (teamOid.HasValue)
			{
				val = false;
				foreach (var t2c in customer.Team2CustomerList)
				{
					if (t2c.TeamOid == teamOid)
						return true;
				}
			}
			return val;
		}

		private String GetBehinderungenList(Customer customer)
		{
			String list = "";
			List<String> behinderungen = new List<string>();
			foreach (var v in customer.ValueList)
			{
				if (v.Entry.Type == ValueListEntryType.DisabilityType)
				{
					behinderungen.Add(v.Entry.Value);
				}
			}

			foreach (var b in behinderungen.OrderBy(a => a))
			{
				if (list.Length > 0)
				{
					list += ", ";
				}
				list += b;
			}
			return list;
		}
	}
}