using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.ServiceModel;

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Configuration;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Plugins;
using BeWo.Service.ServiceContracts;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;
using Utils = BeWo.Service.Core.Utils;
using BS.Shared.DataContracts.Reports;
using BeWo.Service.Reporting;

namespace BeWo.Service.ServiceImplementations
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
    public class AnalysisServiceImp : IAnalysisService
    {
        public CompactCustomerDC CreateCompactCustomerDC(Customer c)
        {
            var dc = new CompactCustomerDC();
            dc.CustomerOid = c.Oid.Value;
            dc.FirstName = c.Person.FirstName;
            dc.LastName = c.Person.LastName;
            dc.DateOfBirth = c.Person.DateOfBirth;
            dc.ActivationType = c.IsActive;
	        dc.Sex = c.Person.Sex;

            return dc;
        }

        public CompactEmployeeDC CreateCompactEmployeeDC(Employee e)
        {
            var dc = new CompactEmployeeDC();
            dc.EmployeeOid = e.Oid.Value;
            dc.FirstName = e.Person.FirstName;
            dc.LastName = e.Person.LastName;

            return dc;
        }

        public List<AccountingAnalysisDC> GetAccountingAnalysis(DateTimeSpan pSpan)
        {
            try
            {
                // return MapperFactory.AccountingTransactionDC_AccountingTransaction.MapToNewDCs(
                // DAOFactory.SearchDAO.FindAccoutingTransactions(pSpan));
                return null;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

	    public List<FLSAnalysisRootDC> GetFLSAnalysis(FLSAnalysisConfigDC config)
	    {
			if (config.ReportType == FLSReportType.Employee)
			{
				if (config.EmployeeOid.HasValue)
				{
					return GetEmployeeFLSAnalysisForEmployee(config);
				}
				return GetEmployeeFLSAnalysis(config);
				
			}
			if (config.ReportType == FLSReportType.Customer)
			{
				if (config.CustomerOid.HasValue)
				{
					return GetCustomerFLSAnalysisForCustomer(config);
				}
				return GetCustomerFLSAnalysis(config);

			}
			if (config.ReportType == FLSReportType.Costbearer)
			{
				return GetCostBearerFLSAnalysis(config);
			}
			return GetTeamFLSAnalysis(config);
			
	    }



	    public List<FLSAnalysisRootDC> GetCostBearerFLSAnalysis(DateTime? startDate, DateTime? endDate,
		    bool fetchServiceRecordNotice, List<long> goalOids)
	    {
		    var config = new FLSAnalysisConfigDC
		    {
			    StartDate = startDate,
			    EndDate = endDate,
			    FetchServiceRecordNotice = fetchServiceRecordNotice,
			    GoalOids = goalOids
		    };

		    return GetCostBearerFLSAnalysis(config);
	    }

		public List<FLSAnalysisRootDC> GetCostBearerFLSAnalysis(FLSAnalysisConfigDC config)
        {
            try
            {
	            int count = 0;

                var lResult = new List<FLSAnalysisRootDC>();

                var rootDC = new FLSAnalysisRootDC();
                rootDC.Groups = new List<FLSAnalysisGroupDC>();
                lResult.Add(rootDC);

                var flsGroupDict = new Dictionary<long, FLSAnalysisGroupDC>();

                foreach (var iCostbearer in DAOFactory.GenericDAO.GetAllActive<CostBearer>())
                {
                    if (iCostbearer.Organisation != null)
                    {
                        var groupDC = new FLSAnalysisGroupDC();
                        groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                        groupDC.Organisation = new CompactOrganisationDC();
                        groupDC.Organisation.OrganisationOid = iCostbearer.Organisation.Oid.Value;
                        groupDC.Organisation.OrganisationVersion = iCostbearer.Organisation.Version.Value;
                        groupDC.Organisation.Name = iCostbearer.Organisation.Name;

                        flsGroupDict.Add(iCostbearer.Oid.Value, groupDC);
                        rootDC.Groups.Add(groupDC);
                    }
                }

                var span = new DateTimeSpan();
                span.StartDateTime = config.StartDate.Value;
                span.EndDateTime = config.EndDate.Value;
                IEnumerable<ServiceRecord> serviceRecordes = DAOFactory.SearchDAO.FindServiceRecordsInSpan(span, config.ShowOnlyMarker ? ServiceRecordTypeId.Content : (ServiceRecordTypeId?) null);

                Dictionary<long, SupportConceptFLSOverviewDC> supportConceptOverviewDict = new Dictionary<long, SupportConceptFLSOverviewDC>();
                Dictionary<String, bool> groupBookingDict = new Dictionary<String, bool>();

                foreach (ServiceRecord sr in serviceRecordes)
                {
                    bool cont = true;
	                
                    if (sr.Customer != null && sr.Customer.IsActive == ActivationTypeId.Deleted)
                    {
                        cont = false;
                    }

                    if (cont && sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
                    {
                        cont = false;
                    }
                    if (cont && sr.GroupOid != null && sr.CostBearer2SupportConceptOid != null)
                    {
                        String key = String.Format("{0}_{1}", sr.GroupOid, sr.CostBearer2SupportConceptOid);
                        if (groupBookingDict.ContainsKey(key))
                            cont = false;
                    }
                    if (cont)
                    {
                        cont = this.IsServiceRecordForGoal(sr, config.GoalOids);
                    }
					if (cont && config.ServiceDescriptionOids != null && config.ServiceDescriptionOids.Count > 0 && !config.ServiceDescriptionOids.Contains(sr.ServiceDescription.Oid.Value))
					{
						cont = false;
					}
					if (cont && config.ShowOnlyMarker && (!sr.ServiceRecordType.HasValue || sr.ServiceRecordType.Value != ServiceRecordTypeId.Content))
					{
						cont = false;
					}
                    if (cont)
                    {
                        ServiceRecordFLSOverviewDC srDC = CreateServiceRecordFLSOverviewDC(sr, false, true);
                        if (sr.GroupOid != null && sr.CostBearer2SupportConceptOid != null)
                        {
                            String key = String.Format("{0}_{1}", sr.GroupOid, sr.CostBearer2SupportConceptOid);
                            groupBookingDict.Add(key, true);
                        }
                        if (sr.CostBearer2SupportConceptOid != null)
                        {
                            CostBearer2SupportConcept cb2sc = sr.CostBearer2SupportConcept;

                            if (flsGroupDict.ContainsKey(cb2sc.CostBearer.Oid.Value))
                            {
                                FLSAnalysisGroupDC groupDC = flsGroupDict[cb2sc.CostBearer.Oid.Value];

                                SupportConceptFLSOverviewDC scDC = null;
                                if (supportConceptOverviewDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                                {
                                    scDC = supportConceptOverviewDict[sr.CostBearer2SupportConceptOid.Value];
                                }

                                if (scDC == null)
                                {
                                    scDC = new SupportConceptFLSOverviewDC();
                                    supportConceptOverviewDict.Add(sr.CostBearer2SupportConceptOid.Value, scDC);

                                    // CostBearer2SupportConcept c2s = null;
                                    // if(c2sDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                                    // c2s = c2sDict[sr.CostBearer2SupportConceptOid.Value];
                                    CostBearer2SupportConcept c2s = sr.CostBearer2SupportConcept;
                                    if (c2s != null)
                                    {
                                        scDC.SupportConcept2CostBearer = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
                                    }

                                    groupDC.SupportConcepts.Add(scDC);
                                }
	                            count++;
                                scDC.ServiceRecords.Add(srDC);
                            }
                        }
                    }
                }

                return lResult;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }


	    public List<FLSAnalysisRootDC> GetCustomerFLSAnalysis(DateTime? startDate, DateTime? endDate, bool fetchApprovedFLS,
		    bool fetchServiceRecordNotice, long? employeeOid, List<long> goalOids)
		{
			var config = new FLSAnalysisConfigDC
			{
				StartDate = startDate,
				EndDate = endDate,
				FetchApprovedFLS = fetchApprovedFLS,
				FetchServiceRecordNotice = fetchServiceRecordNotice,
				EmployeeOid = employeeOid,
				GoalOids = goalOids
			};

			return GetCustomerFLSAnalysis(config);
		}

        public List<FLSAnalysisRootDC> GetCustomerFLSAnalysis(FLSAnalysisConfigDC config)
        {
            try
            {
                var lResult = new List<FLSAnalysisRootDC>();

                foreach (var iCustomer in DAOFactory.GenericDAO.GetAllActiveAndArchived<Customer>())
                {
                    lResult.Add(this.CreateCustomerFLSOverviewDC(iCustomer, config));
                }

                return lResult;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

		
		public List<FLSAnalysisRootDC> GetCustomerFLSAnalysisForCustomer(long customerOid, DateTime? startDate, DateTime? endDate, bool fetchApprovedFLS, bool fetchServiceRecordNotice, long? employeeOid, List<long> goalOids)
		{
			var config = new FLSAnalysisConfigDC
			{
				CustomerOid = customerOid,
				StartDate = startDate,
				EndDate = endDate,
				FetchApprovedFLS = fetchApprovedFLS,
				FetchServiceRecordNotice = fetchServiceRecordNotice,
				EmployeeOid = employeeOid,
				GoalOids = goalOids
			};

			return GetCustomerFLSAnalysisForCustomer(config);
		}

		public List<FLSAnalysisRootDC> GetCustomerFLSAnalysisForCustomer(FLSAnalysisConfigDC config)
        {
            try
            {
                var lResult = new List<FLSAnalysisRootDC>();

                var customer = DAOFactory.GenericDAO.LoadByID<Customer>(config.CustomerOid.Value);

                lResult.Add(this.CreateCustomerFLSOverviewDC(customer, config));

                return lResult;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

		
		public List<FLSAnalysisRootDC> GetEmployeeFLSAnalysis(DateTime? startDate, DateTime? endDate, bool fetchApprovedFLS, bool fetchServiceRecordNotice, long? customerOid, List<long> goalOids, String text1, String text2, String text3, String text4, String text5)
		{
			var config = new FLSAnalysisConfigDC
			{
				StartDate = startDate,
				EndDate = endDate,
				FetchApprovedFLS = fetchApprovedFLS,
				FetchServiceRecordNotice = fetchServiceRecordNotice,
				CustomerOid = customerOid,
				GoalOids = goalOids,
				Text1 = text1,
				Text2 = text2,
				Text3 = text3,
				Text4 = text4,
				Text5 = text5
			};

			return GetEmployeeFLSAnalysis(config);
		}

		public List<FLSAnalysisRootDC> GetEmployeeFLSAnalysis(FLSAnalysisConfigDC config)
        {
            try
            {
	            var settings = AppSettings.CreateSettings();

	            config.ShouldAnalyzeArchivedEmployees = true; //###Todo NACH Update wieder raus

				var employees = config.ShouldAnalyzeArchivedEmployees ? DAOFactory.GenericDAO.GetAllActiveAndArchived<Employee>() : DAOFactory.GenericDAO.GetAllActive<Employee>();

				// (Archiviert) hinter dem Vornamen archivierter Mitarbeiter anzeigen?
				//if(config.ShouldAnalyzeArchivedEmployees)
				//	foreach (var emp in employees)
				//	{
				//		if (emp.IsActive.Equals(ActivationTypeId.Archived))
				//			emp.Person.FirstName += " (Archiviert)";
				//	}

	            return (from iEmployee in employees where CheckEmployeeTextProperties(iEmployee, config.Text1, config.Text2, config.Text3, config.Text4, config.Text5) select CreateEmployeeFLSRootDC(iEmployee, config, settings.ShowRoundedDurationInEmployeeAnalysis)).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        private bool CheckEmployeeTextProperties(Employee emp, string text1, string text2, string text3, string text4, string text5)
        {
            bool valid = true;
            if (!String.IsNullOrEmpty(text1))
            {
                valid = text1.Equals(emp.Text1);
            }
            if (valid && !String.IsNullOrEmpty(text2))
            {
                valid = text2.Equals(emp.Text2);
            }
            if (valid && !String.IsNullOrEmpty(text3))
            {
                valid = text3.Equals(emp.Text3);
            }
            if (valid && !String.IsNullOrEmpty(text4))
            {
                valid = text4.Equals(emp.Text4);
            }
            if (valid && !String.IsNullOrEmpty(text5))
            {
                valid = text5.Equals(emp.Text5);
            }
            return valid;
        }

		public List<FLSAnalysisRootDC> GetEmployeeFLSAnalysisForEmployee(long employeeOid, DateTime? startDate, DateTime? endDate, bool fetchApprovedFLS, bool fetchServiceRecordNotice, long? customerOid, List<long> goalOids)
		{
			var config = new FLSAnalysisConfigDC
			{
				EmployeeOid = employeeOid,
				StartDate = startDate,
				EndDate = endDate,
				FetchApprovedFLS = fetchApprovedFLS,
				FetchServiceRecordNotice = fetchServiceRecordNotice,
				CustomerOid = customerOid,
				GoalOids = goalOids
			};

			return GetEmployeeFLSAnalysisForEmployee(config);
		}

		public List<FLSAnalysisRootDC> GetEmployeeFLSAnalysisForEmployee(FLSAnalysisConfigDC config)
        {
            try
            {
                var lResult = new List<FLSAnalysisRootDC>();

				var settings = AppSettings.CreateSettings();

                var emp = DAOFactory.GenericDAO.LoadByID<Employee>(config.EmployeeOid.Value);

                lResult.Add(CreateEmployeeFLSRootDC(emp, config, settings.ShowRoundedDurationInEmployeeAnalysis));

                return lResult;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

		public List<FLSAnalysisRootDC> GetTeamFLSAnalysis(DateTime? startDate, DateTime? endDate, bool fetchServiceRecordNotice, List<long> goalOids, List<long> teamOids)
		{
			var config = new FLSAnalysisConfigDC
			{
				StartDate = startDate,
				EndDate = endDate,
				FetchServiceRecordNotice = fetchServiceRecordNotice,
				GoalOids = goalOids,
				TeamOids = teamOids
			};

			return GetTeamFLSAnalysis(config);
		}

		public List<FLSAnalysisRootDC> GetTeamFLSAnalysis(FLSAnalysisConfigDC config)
        {
            try
            {
				int count = 0;

	            var settings = AppSettings.CreateSettings();
                var lResult = new List<FLSAnalysisRootDC>();

                FLSAnalysisRootDC rootDC = new FLSAnalysisRootDC();
                rootDC.Groups = new List<FLSAnalysisGroupDC>();
                lResult.Add(rootDC);

                Dictionary<long, FLSAnalysisGroupDC> flsGroupsByCustomerOidDict = new Dictionary<long, FLSAnalysisGroupDC>();
                Dictionary<long, Team> teamOidDict = new Dictionary<long, Team>();

                IList<Team> teams = DAOFactory.GenericDAO.GetAllActive<Team>();
                foreach (var team in teams)
                {
                    teamOidDict.Add(team.Oid.Value, team);
                }

                IList<Team2Customer> team2customers = DAOFactory.GenericDAO.GetAll<Team2Customer>();

                foreach (var t2c in team2customers)
                {
                    if ((config.TeamOids == null || config.TeamOids.Contains(t2c.TeamOid.Value)) && teamOidDict.ContainsKey(t2c.TeamOid.Value))
                    {
                        Team team = teamOidDict[t2c.TeamOid.Value];

                        FLSAnalysisGroupDC groupDC = new FLSAnalysisGroupDC();
                        groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                        groupDC.Team = new CompactTeamDC();
                        groupDC.Team.TeamOid = team.Oid.Value;
                        groupDC.Team.Name = team.Name;

                        if (!flsGroupsByCustomerOidDict.ContainsKey(t2c.CustomerOid.Value))
                            flsGroupsByCustomerOidDict.Add(t2c.CustomerOid.Value, groupDC);


                        rootDC.Groups.Add(groupDC);
                    }
                }

                var span = new DateTimeSpan();
				span.StartDateTime = config.StartDate.Value;
				span.EndDateTime = config.EndDate.Value;
				IEnumerable<ServiceRecord> serviceRecordes = DAOFactory.SearchDAO.FindServiceRecordsInSpan(span, config.ShowOnlyMarker ? ServiceRecordTypeId.Content : (ServiceRecordTypeId?)null);

                Dictionary<long, SupportConceptFLSOverviewDC> supportConceptOverviewDict = new Dictionary<long, SupportConceptFLSOverviewDC>();
	            decimal archived = 0;
				decimal notarchived = 0;
                foreach (ServiceRecord sr in serviceRecordes)
                {
					
                    bool cont = true;
					if (sr.Customer != null && sr.Customer.IsActive == ActivationTypeId.Deleted)
                        cont = false;
                    if (cont && sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
                        cont = false;
                    if (cont)
						cont = IsServiceRecordForGoal(sr, config.GoalOids);
					if (cont && config.ServiceDescriptionOids != null && config.ServiceDescriptionOids.Count > 0 && !config.ServiceDescriptionOids.Contains(sr.ServiceDescription.Oid.Value))
					{
						cont = false;
					}
					if (cont && config.ShowOnlyMarker && (!sr.ServiceRecordType.HasValue || sr.ServiceRecordType.Value != ServiceRecordTypeId.Content))
					{
						cont = false;
					}
                    if (cont)
                    {
						//if (sr.Customer.IsActive == ActivationTypeId.Archived || sr.SupportConcept.IsActive == ActivationTypeId.Archived)
						//{
						//	archived += sr.RoundedDuration;
						//}
						//else
						//{
						//	notarchived += sr.RoundedDuration;
						//}
                        ServiceRecordFLSOverviewDC srDC = CreateServiceRecordFLSOverviewDC(sr, false, settings.ShowRoundedDurationInEmployeeAnalysis);

                        if (sr.CostBearer2SupportConceptOid != null)
                        {
                            CostBearer2SupportConcept cb2sc = sr.CostBearer2SupportConcept;

                            if (flsGroupsByCustomerOidDict.ContainsKey(sr.CustomerOid.Value))
                            {
                                FLSAnalysisGroupDC groupDC = flsGroupsByCustomerOidDict[sr.CustomerOid.Value];



                                SupportConceptFLSOverviewDC scDC = null;
                                if (supportConceptOverviewDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                                    scDC = supportConceptOverviewDict[sr.CostBearer2SupportConceptOid.Value];

                                if (scDC == null)
                                {
                                    scDC = new SupportConceptFLSOverviewDC();
                                    supportConceptOverviewDict.Add(sr.CostBearer2SupportConceptOid.Value, scDC);

                                    //CostBearer2SupportConcept c2s = null;
                                    //if(c2sDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                                    //    c2s = c2sDict[sr.CostBearer2SupportConceptOid.Value];
                                    CostBearer2SupportConcept c2s = sr.CostBearer2SupportConcept;
                                    if (c2s != null)
                                    {
                                        scDC.SupportConcept2CostBearer = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
                                    }


                                    groupDC.SupportConcepts.Add(scDC);
                                }
	                            count++;
                                scDC.ServiceRecords.Add(srDC);
                            }
                        }

                    }
                }

                return lResult;
            }
            catch (Exception e)
            {
                throw (BeWo.Service.Core.Utils.CreateBeWoFaultException(e));
            }
        }

        public List<CompactSupportConceptDC> GetExpiringSupportConcepts(long? employeeOid, DateTime expiredUntil)
        {
            try
            {
				var hcg = PluginLoader.FindClass<HomeContentGenerator>();

				return hcg.GetExpiringSupportConcepts(employeeOid, expiredUntil);
                
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<LoginDC> GetLastLogins(string loginName)
        {
            try
            {
                return MapperFactory.LoginDC_Login.MapToNewDCs(DAOFactory.SearchDAO.FindLastLogins(loginName));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

	    public List<FinanceOverviewItemDC> GetOutstandingReceivables(bool showOnlyOutstanding, bool showOnlyArchivedSCs)
	    {
		    return GetOutstandingReceivables(showOnlyOutstanding, showOnlyArchivedSCs, null, null);
	    }

	    public List<FinanceOverviewItemDC> GetOutstandingReceivables(bool showOnlyOutstanding, bool showOnlyArchivedSCs, DateTime? start, DateTime? end)
        {
            try
            {
                List<FinanceOverviewItemDC> result = new List<FinanceOverviewItemDC>();

				var financeItemsByCb2scOid = new Dictionary<long, FinanceOverviewItemDC>();

				IEnumerable<SupportConcept> scList = DAOFactory.SearchDAO.GetAllActiveAndArchivedSupportConcepts();
				foreach (SupportConcept sc in scList)
				{
					foreach (CostBearer2SupportConcept cb2sc in sc.CostBearer2SupportConceptList)
					{
						if (!financeItemsByCb2scOid.ContainsKey(cb2sc.Oid.Value))
						{
							bool cont = true;

							if (end.HasValue && cb2sc.StartDate.HasValue && cb2sc.StartDate > end)
							{
								cont = false;
							}

							if (cont)
							{
								DateTime? hilfeplanEnde = cb2sc.EndDate;

								if (hilfeplanEnde.HasValue && cb2sc.SupportConcept.Customer.TerminationDate.HasValue &&
								    cb2sc.SupportConcept.Customer.TerminationDate < hilfeplanEnde)
								{
									hilfeplanEnde = cb2sc.SupportConcept.Customer.TerminationDate;
								}
								if (start.HasValue && hilfeplanEnde.HasValue && hilfeplanEnde < start)
								{
									cont = false;
								}
							}
							if (cont)
							{
								FinanceOverviewItemDC dc = new FinanceOverviewItemDC();
								result.Add(dc);

								dc.SupportConcept = this.CreateCompactSupportConceptDC(sc);
								dc.CostBearer = this.CreateCompactCostBearerDC(cb2sc);
								dc.AmountTotal = this.GetTotalAmount(cb2sc);

								financeItemsByCb2scOid.Add(cb2sc.Oid.Value, dc);
							}
						}
					}
				}
				
				IEnumerable<AccountingTransaction> atList = DAOFactory.SearchDAO.GetAllAccountingTransactionsWithDetails();

                foreach (AccountingTransaction at in atList)
                {
                    if (at.CostBearer2SupportConcept == null ||
                        (at.CostBearer2SupportConcept.SupportConcept.IsActive != ActivationTypeId.Deleted &&
                         at.CostBearer2SupportConcept.SupportConcept.Customer.IsActive != ActivationTypeId.Deleted))
                    {
                        FinanceOverviewItemDC dc;
                        long oid = -1;
                        if (at.CostBearer2SupportConcept != null)
                        {
                            oid = at.CostBearer2SupportConcept.Oid.Value;
                        }

						if (financeItemsByCb2scOid.ContainsKey(oid))
                        {
							dc = financeItemsByCb2scOid[oid];
							dc.AmountPaid += at.Amount;

							//AccountingTransactionDC atdc = this.CreateAccountingTransactionDC(at);
							//dc.AccountingTransactions.Add(atdc);
                        }
						//else
						//{
						//	dc = new FinanceOverviewItemDC();
						//	result.Add(dc);

						//	if (at.CostBearer2SupportConcept != null)
						//	{
						//		dc.SupportConcept =
						//			this.CreateCompactSupportConceptDC(at.CostBearer2SupportConcept.SupportConcept);
						//		dc.CostBearer = this.CreateCompactCostBearerDC(at.CostBearer2SupportConcept);
						//		dc.AmountTotal = this.GetTotalAmount(at.CostBearer2SupportConcept);
						//	}

						//	financeItemsByCb2scOid.Add(oid, dc);
						//}

                       
                    }
                }

                

                return result.OrderBy(
                                      item =>
                                      {
                                          if (item.SupportConcept == null || item.SupportConcept.Customer == null)
                                          {
                                              return string.Empty;
                                          }

                                          return item.SupportConcept.Customer.LastName + ", " + item.SupportConcept.Customer.FirstName;
                                      }).ToList();
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactPersonDC> GetPersonsHavingBirthday(DateTime birthdayUntil)
        {
            try
            {
				var hcg = PluginLoader.FindClass<HomeContentGenerator>();

	            return hcg.GetPersonsHavingBirthday(birthdayUntil);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<SupportConceptOverviewDC> GetSupportConceptAnalysis(long? currentEmployeeOid,
                                                                        bool showOnlyRelatedSCs,
                                                                        bool showOnlyArchivedSCs,
                                                                        DateTime? appointedDate)
        {
            try
            {
                DateTime maxDate = appointedDate.HasValue
                                       ? appointedDate.Value.AddDays(1)
                                       : DateTime.MaxValue;

                var lResult = new List<SupportConceptOverviewDC>();

                foreach (var iCb2Sc in DAOFactory.GenericDAO.GetAllActive<CostBearer2SupportConcept>())
                {
                    if (iCb2Sc.Oid.HasValue && iCb2Sc.Oid.Value.Equals(66))
                    {
                        
                    }

					var calc = PluginLoader.FindClass<Calculations>(iCb2Sc.CostBearer.ID) ?? Calculations.GetInstance(iCb2Sc.CostBearer.ID);
                    var iDC = new SupportConceptOverviewDC();

                    if (currentEmployeeOid != null)
                    {
                        foreach (var e2c in iCb2Sc.SupportConcept.Customer.Employee2CustomerList)
                        {
                            if (!iDC.IsRelatedToEmployee)
                            {
                                if (currentEmployeeOid.Value == e2c.EmployeeOid.Value)
                                {
                                    iDC.IsRelatedToEmployee = true;
                                }
                            }
                        }
                    }

                    iDC.ActivationType = iCb2Sc.SupportConcept.IsActive;
                    if (iDC.ActivationType == ActivationTypeId.Active && iCb2Sc.SupportConcept.Customer.IsActive != ActivationTypeId.Active)
                    {
                        iDC.ActivationType = iCb2Sc.SupportConcept.Customer.IsActive;
                    }

                    bool cont = (showOnlyArchivedSCs && iDC.ActivationType == ActivationTypeId.Archived) || (!showOnlyArchivedSCs && iDC.ActivationType == ActivationTypeId.Active);
                    if (cont && (!showOnlyRelatedSCs || iDC.IsRelatedToEmployee))
                    {
                        iDC.CalculationDate = DateTime.Now.Date;
                        iDC.RequestedStartDate = iCb2Sc.RequestedStartDate;
                        iDC.RequestedEndDate = iCb2Sc.RequestedEndDate;
                        iDC.SupportConceptOid = iCb2Sc.SupportConcept.Oid.Value;
						iDC.CostBearer2SupportConceptOid = iCb2Sc.Oid.Value;
                        iDC.CostBearer = iCb2Sc.CostBearer.Organisation != null
                                             ? iCb2Sc.CostBearer.Organisation.Name
                                             : string.Empty;
						iDC.CostBearerId = iCb2Sc.CostBearer.ID;
                        iDC.CustomerOid = iCb2Sc.SupportConcept.Customer.Oid.Value;
	                    iDC.CustomerFirstName = iCb2Sc.SupportConcept.Customer.Person.FirstName;
                        iDC.CustomerLastName = iCb2Sc.SupportConcept.Customer.Person.LastName;

                        var costRates = iCb2Sc.CostBearer.CostRatePeriods.MapToNewDCs();

                        iDC.ServiceUnit = costRates.GetCurrentlyValidRate(CostRatePeriodType.MinutesPerServiceUnit);
                        if (iDC.ServiceUnit == null)
                        {
                            iDC.ServiceUnit = new CostRatePeriodDC();
                            iDC.ServiceUnit.CostRateType = CostRatePeriodType.MinutesPerServiceUnit;
                            iDC.ServiceUnit.UnitName = "FLS";
                            iDC.ServiceUnit.CostRateValue = 60;
                        }
                        iDC.CurrentHourlyRate = costRates.GetCurrentlyValidRateValue(CostRatePeriodType.HourlyRate) ?? 0m;
                        iDC.CurrentRateFactor = costRates.GetCurrentlyValidRateValue(CostRatePeriodType.RateFactor) ?? 0m;

                        var relDC = iCb2Sc.MapToNewDC();

                        var recordDCs = (from sr in iCb2Sc.ServiceRecords where sr.Start.Value < maxDate select MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDC(sr)).ToList();


                        iDC.FLSRecordedTillNow = calc.GetBillableDurationInMinutes(recordDCs) / 60m;

                        var notBillableAbsenceTimes = calc.GetHoursNotBillableDueToAbsenceTimes(relDC, recordDCs,
                                                                                                iCb2Sc.SupportConcept.Customer.GetAbsencesTimesNotBillableWholeWeeks(), false,
                                                                                                false);
                        var notBillableMoreThanApproved = calc.GetHoursNotBillableDueToMoreThanApproved(relDC, recordDCs,
                                                                                                        false, true);
	                    iDC.FLSBilledTillNow = iDC.FLSRecordedTillNow;
                                               //- notBillableAbsenceTimes
                                               //- notBillableMoreThanApproved;

                        

                        decimal lDurationInWeeksTillNow = calc.GetDurationInWeeksTillNow(relDC, appointedDate) ?? 0;
                        decimal lDurationInWeeks = calc.GetDurationInWeeks(relDC) ?? 0;

                        if (iCb2Sc.Status == CostBearer2SupportConceptStatus.Approved)
                        {
                            iDC.IsApproved = true;

                            if (iCb2Sc.ApprovedStartDate != null && iCb2Sc.ApprovedEndDate != null)
                            {
                                iDC.ApprovedStartDate = iCb2Sc.ApprovedStartDate.Value;
                                iDC.ApprovedEndDate = iCb2Sc.ApprovedEndDate.Value;
                                //lDurationInWeeks = Convert.ToDecimal((iDC.ApprovedEndDate.Value - iDC.ApprovedStartDate.Value).Days + 1) / 7;

                                //lCalcDate = lCalcDate > iCb2Sc.ApprovedEndDate
                                //                ? iCb2Sc.ApprovedEndDate.Value.Date.AddDays(1)
                                //                : lCalcDate;
                                //lDurationInWeeksTillNow = Convert.ToDecimal((lCalcDate - iCb2Sc.ApprovedStartDate.Value).Days) / 7m;
                            }
                        }
                        else
                        {
                            iDC.IsApproved = false;

                            //if (iCb2Sc.RequestedStartDate != null && iCb2Sc.RequestedEndDate != null)
                            //{
                                //lDurationInWeeks = Convert.ToDecimal((iCb2Sc.RequestedEndDate.Value - iCb2Sc.RequestedStartDate.Value).Days + 1) / 7;

                                //lCalcDate = lCalcDate > iCb2Sc.RequestedEndDate
                                //                ? iCb2Sc.RequestedEndDate.Value.Date
                                //                : lCalcDate;
                                //lDurationInWeeksTillNow = Convert.ToDecimal((lCalcDate - iCb2Sc.RequestedStartDate.Value).Days) / 7m;
                            //}
                        }

                        iDC.FLSApprovedPerWeek = calc.GetApprovedHoursPerWeekAverage(relDC, true) ?? 0m;
                        
                        decimal? flsTotal = calc.GetApprovedHoursTotal(relDC, true);

                        iDC.FLSApprovedSum = flsTotal ?? 0m;

                        var approvedTillNow = calc.GetApprovedHoursTillNow(relDC, appointedDate);
                        iDC.FLSApprovedTillNow = approvedTillNow ?? 0;

                        //if (flsTotal.HasValue && lDurationInWeeks != 0)
                        //{
                        //    iDC.FLSApprovedTillNow = flsTotal.Value * ((lDurationInWeeksTillNow + (1m / 7m)) / lDurationInWeeks);
                        //}
                        //else
                        //{
                        //    iDC.FLSApprovedTillNow = iDC.FLSApprovedPerWeek * (lDurationInWeeksTillNow + (1m / 7m));
                        //}

                        if (iDC.FLSApprovedSum <= 0)
                        {
                            iDC.FLSRecordedTillNowInPercent = 0;
                        }
                        else
                        {
                            iDC.FLSRecordedTillNowInPercent = iDC.FLSRecordedTillNow / iDC.FLSApprovedSum * 100;
                        }

                        iDC.FLSDifferenceApprovedRecordedTillNow = iDC.FLSRecordedTillNow - iDC.FLSApprovedTillNow;

                        if (iDC.FLSApprovedTillNow <= 0)
                        {
                            iDC.FLSDifferenceApprovedRecordedTillNowInPercent = 0;
                        }
                        else
                        {
                            iDC.FLSDifferenceApprovedRecordedTillNowInPercent = iDC.FLSRecordedTillNow / iDC.FLSApprovedTillNow * 100;
                        }

                        iDC.FLSOpen = iDC.FLSApprovedSum - iDC.FLSRecordedTillNow;
                        iDC.OpenWeeks = lDurationInWeeks - lDurationInWeeksTillNow;

                        //TODO kostenträger spezifisch!? in Calculations verlagern!
                        iDC.OpenMonths = iDC.OpenWeeks / 4.34m;

                        if (iDC.OpenWeeks <= 0)
                        {
                            iDC.FLSOpenPerWeek = 0;
                        }
                        else
                        {
                            iDC.FLSOpenPerWeek = iDC.FLSOpen / iDC.OpenWeeks;
                        }

                        iDC.WeeksTotal = lDurationInWeeks;
                        if (iDC.WeeksTotal != 0)
                        {
                            iDC.DurationPercentage = (lDurationInWeeksTillNow / iDC.WeeksTotal) * 100;
                        }

                        lResult.Add(iDC);

                        iDC.BEApprovedPerWeek = iDC.ServiceUnit.GetHoursInBE(iDC.FLSApprovedPerWeek);
                        iDC.BEApprovedSum = iDC.ServiceUnit.GetHoursInBE(iDC.FLSApprovedSum);
                        iDC.BEApprovedTillNow = iDC.ServiceUnit.GetHoursInBE(iDC.FLSApprovedTillNow);
                        iDC.BEBilledTillNow = iDC.ServiceUnit.GetHoursInBE(iDC.FLSBilledTillNow);
                        iDC.BEDifferenceApprovedRecordedTillNow = iDC.ServiceUnit.GetHoursInBE(iDC.FLSDifferenceApprovedRecordedTillNow);
                        iDC.BEDifferenceApprovedRecordedTillNowInPercent = iDC.ServiceUnit.GetHoursInBE(iDC.FLSDifferenceApprovedRecordedTillNowInPercent);
                        iDC.BEOpen = iDC.ServiceUnit.GetHoursInBE(iDC.FLSOpen);
                        iDC.BEOpenPerWeek = iDC.ServiceUnit.GetHoursInBE(iDC.FLSOpenPerWeek);
						if (iDC.BEOpenPerWeek > iDC.BEOpen)
							iDC.BEOpenPerWeek = iDC.BEOpen;
                        iDC.BERecordedTillNow = iDC.ServiceUnit.GetHoursInBE(iDC.FLSRecordedTillNow);
                        iDC.BERecordedTillNowInPercent = iDC.ServiceUnit.GetHoursInBE(iDC.FLSRecordedTillNowInPercent);
                    }
                }

                return lResult;
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<CompactSupportConceptDC> GetSupportConceptsWithConferenceDate(long? employeeOid, DateTime conferenceDateUntil)
        {
            try
            {
                return MapperFactory.CompactSupportConceptDC_SupportConcept.MapToNewDCs(DAOFactory.SearchDAO.FindSupportConceptsWithConferenceDate(employeeOid, conferenceDateUntil));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<TaskDC> GetTasksForEmployee(long employeeOid)
        {
            try
            {
                return MapperFactory.TaskDC_Task.MapToNewDCs(DAOFactory.SearchDAO.FindTasksForEmployee(employeeOid));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public List<TaskDC> GetTasksForEmployeeByDate(long employeeOid,DateTime date)
        {
            try
            {
                return MapperFactory.TaskDC_Task.MapToNewDCs(DAOFactory.SearchDAO.GetTasksForEmployeeByDate(employeeOid, date));
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }


        private AccountingTransactionDC CreateAccountingTransactionDC(AccountingTransaction at)
        {
            var dc = new AccountingTransactionDC();

            dc.AccountingTransactionOid = at.Oid;
            dc.AccountingTransactionVersion = at.Version;
            dc.Amount = at.Amount;
            dc.InsertedOn = at.InsTs;
            dc.InsUser = at.InsUser;

            var lCat = at.ValueList.SingleOrDefault(entry => entry.Entry.Type == ValueListEntryType.AccountingTransactionType);
            if (lCat != null)
            {
                dc.Category = MapperFactory.ValueListEntryDC_ValueListEntry.MapToNewDC(lCat.Entry);
            }

            dc.Notice = at.Notice;
            dc.BookingDate = at.BookingDate;

            return dc;
        }

        private CompactCostBearerDC CreateCompactCostBearerDC(CostBearer2SupportConcept entity)
        {
            var dc = new CompactCostBearerDC();

            if (entity.CostBearer != null && entity.CostBearer.Organisation != null)
            {
                var orgDC = new CompactOrganisationDC();
                orgDC.Name = entity.CostBearer.Organisation.Name;
                orgDC.OrganisationOid = entity.CostBearer.Organisation.Oid.Value;
                dc.Organisation = orgDC;

                dc.IsCalculatingWithFactor = entity.CostBearer.IsCalculatingWithFactor;

                // dc.Street = entity.CostBearer.Organisation.Address.Street;
                // dc.PostalCode = entity.CostBearer.Organisation.Address.PostalCode;
                // dc.Town = entity.CostBearer.Organisation.Address.Town;
            }

            dc.CostBearer2SupportConceptOid = entity.Oid.Value;
            dc.CustomerReferenceNumber = entity.CustomerReferenceNumber;
            dc.RequestedStartDate = entity.RequestedStartDate;
            dc.RequestedEndDate = entity.RequestedEndDate;
            dc.ApprovedStartDate = entity.ApprovedStartDate;
            dc.ApprovedEndDate = entity.ApprovedEndDate;

            // dc.ApprovedFLS = entity.ApprovedFLS;
            // dc.ApprovedFLSTotal = entity.ApprovedFLSTotal;
            dc.SupportConceptStatus = entity.Status;

            return dc;
        }

        private CompactSupportConceptDC CreateCompactSupportConceptDC(SupportConcept entity)
        {
            var dc = new CompactSupportConceptDC();

            dc.SupportConceptOid = entity.Oid.Value;
            dc.SupportConceptVersion = entity.Version.Value;

            dc.ActivationType = entity.IsActive;
            dc.ConferenceDate = entity.ConferenceDate;

            dc.Customer = this.CreateCompactCustomerDC(entity.Customer);

            return dc;
        }

		private FLSAnalysisRootDC CreateCustomerFLSOverviewDC(Customer customer, FLSAnalysisConfigDC config)
        {
            var rootDC = new FLSAnalysisRootDC();
            rootDC.Groups = new List<FLSAnalysisGroupDC>();
            rootDC.Customer = MapperFactory.CompactCustomerDC_Customer.MapToNewDC(customer);

            IList<ServiceRecord> serviceRecordes = null;

            if (config.StartDate != null && config.EndDate != null)
            {
                var span = new DateTimeSpan();
                span.StartDateTime = config.StartDate.Value;
                span.EndDateTime = config.EndDate.Value;
				serviceRecordes = DAOFactory.SearchDAO.FindCustomerServiceRecords(customer.Oid.Value, span, null, config.ShowOnlyMarker ? ServiceRecordTypeId.Content : (ServiceRecordTypeId?)null);
            }
            else
            {
                serviceRecordes = customer.ServiceRecordList;
            }

            Dictionary<long, FLSAnalysisGroupDC> flsGroupDict = new Dictionary<long, FLSAnalysisGroupDC>();
            Dictionary<string, SupportConceptFLSOverviewDC> supportConceptOverviewDict = new Dictionary<string, SupportConceptFLSOverviewDC>();

            
            bool createGroups = true;

			if (config.EmployeeOid != null)
            {
                createGroups = false;
                foreach (ServiceRecord sr in serviceRecordes)
                {
					if (sr.Employee != null && sr.Employee.Oid.Value == config.EmployeeOid.Value)
                    {
                        createGroups = true;
                    }
                }
            }

            if (createGroups)
            {
                Dictionary<long, ServiceRecord> groupBookingDict = new Dictionary<long, ServiceRecord>();
                foreach (ServiceRecord sr in serviceRecordes)
                {
                    bool cont = true;
                    if (sr.Employee != null && sr.Employee.IsActive == ActivationTypeId.Deleted)
                    {
                        cont = false;
                    }

                    if (cont && sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
                    {
                        cont = false;
                    }

                    if (cont && sr.GroupOid != null && groupBookingDict.ContainsKey(sr.GroupOid.Value))
                    {
                        cont = false;
                    }

                    if (cont)
                    {
						cont = this.IsServiceRecordForGoal(sr, config.GoalOids);
                    }
					if (cont && config.ServiceDescriptionOids != null && config.ServiceDescriptionOids.Count > 0 && !config.ServiceDescriptionOids.Contains(sr.ServiceDescription.Oid.Value))
					{
						cont = false;
					}
					if (cont && config.ShowOnlyMarker && (!sr.ServiceRecordType.HasValue || sr.ServiceRecordType.Value != ServiceRecordTypeId.Content))
					{
						cont = false;
					}
                    if (cont)
                    {
                        ServiceRecordFLSOverviewDC srDC = CreateServiceRecordFLSOverviewDC(sr, true, true);

                        if (sr.GroupOid != null)
                        {
                            groupBookingDict.Add(sr.GroupOid.Value, sr);
                        }

                        if (sr.CostBearer2SupportConceptOid != null && sr.EmployeeOid != null)
                        {
                            FLSAnalysisGroupDC groupDC = null;

                            if (flsGroupDict.ContainsKey(sr.EmployeeOid.Value))
                            {
                                groupDC = flsGroupDict[sr.EmployeeOid.Value];
                            }

                            if (groupDC == null)
                            {
                                groupDC = new FLSAnalysisGroupDC();
                                groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                                flsGroupDict.Add(sr.EmployeeOid.Value, groupDC);

                                Employee e = sr.Employee;
                                if (e != null)
                                {
                                    groupDC.Employee = this.CreateCompactEmployeeDC(e);
                                }

                                rootDC.Groups.Add(groupDC);
                            }

                            SupportConceptFLSOverviewDC scDC = null;
                            if (supportConceptOverviewDict.ContainsKey(sr.EmployeeOid.Value + "_" + sr.CostBearer2SupportConceptOid.Value))
                            {
                                scDC = supportConceptOverviewDict[sr.EmployeeOid.Value + "_" + sr.CostBearer2SupportConceptOid.Value];
                            }

                            if (scDC == null)
                            {
                                scDC = new SupportConceptFLSOverviewDC();
                                supportConceptOverviewDict.Add(sr.EmployeeOid.Value + "_" + sr.CostBearer2SupportConceptOid.Value, scDC);

                                CostBearer2SupportConcept c2s = sr.CostBearer2SupportConcept;
                                if (c2s != null)
                                {
                                    scDC.SupportConcept2CostBearer = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
                                }

                                groupDC.SupportConcepts.Add(scDC);
                            }

                            scDC.ServiceRecords.Add(srDC);
                        }
                    }
                }
            }

            return rootDC;
        }

        private FLSAnalysisRootDC CreateEmployeeFLSRootDC(Employee emp, FLSAnalysisConfigDC config, bool useRoundedDuration)
        {
            FLSAnalysisRootDC rootDC = new FLSAnalysisRootDC();
            rootDC.Groups = new List<FLSAnalysisGroupDC>();
            rootDC.Employee = MapperFactory.CompactEmployeeDC_Employee.MapToNewDC(emp);

            Contract contract = emp.LastContract;
            if (contract != null && contract.WeeklyFLS.HasValue)
            {
                rootDC.SollFLSPerWeek = contract.WeeklyFLS.Value;
            }

            IList<ServiceRecord> serviceRecords = null;

			if (config.StartDate != null && config.EndDate != null)
            {
                var span = new DateTimeSpan();
				span.StartDateTime = config.StartDate.Value;
				span.EndDateTime = config.EndDate.Value;
				serviceRecords = DAOFactory.SearchDAO.FindEmployeeServiceRecords(emp.Oid.Value, span, config.CustomerOid, config.ShowOnlyMarker ? ServiceRecordTypeId.Content : (ServiceRecordTypeId?)null);
            }
            else
            {
                serviceRecords = emp.ServiceRecordList;
            }

            Dictionary<long, FLSAnalysisGroupDC> flsGroupDict = new Dictionary<long, FLSAnalysisGroupDC>();
            Dictionary<long, SupportConceptFLSOverviewDC> supportConceptOverviewDict = new Dictionary<long, SupportConceptFLSOverviewDC>();

            SupportConceptFLSOverviewDC otherDC = null;
            Dictionary<long, ServiceRecord> groupBookingDict = new Dictionary<long, ServiceRecord>();
            Dictionary<long, string> varFieldDefs = null;
            foreach (ServiceRecord sr in serviceRecords)
            {
                bool cont = true;

				if (sr.Customer != null && sr.Customer.IsActive == ActivationTypeId.Deleted)
                {
                    cont = false;
                }

                if (cont && sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
                {
                    cont = false;
                }

                if (cont && sr.GroupOid != null && groupBookingDict.ContainsKey(sr.GroupOid.Value))
                {
                    cont = false;
                }

                if (cont)
                {
                    cont = this.IsServiceRecordForGoal(sr, config.GoalOids);
                }

				if (cont && config.ServiceDescriptionOids != null && config.ServiceDescriptionOids.Count > 0 && !config.ServiceDescriptionOids.Contains(sr.ServiceDescription.Oid.Value))
				{
					cont = false;
				}
				if (cont && config.ShowOnlyMarker && (!sr.ServiceRecordType.HasValue || sr.ServiceRecordType.Value != ServiceRecordTypeId.Content))
				{
					cont = false;
				}
                if (cont)
                {
                    ServiceRecordFLSOverviewDC srDC = CreateServiceRecordFLSOverviewDC(sr, true, useRoundedDuration);
                    
                    if (srDC.GroupRoundedDuration != null && useRoundedDuration)
                    {
						//###CB Rundung bei Employee
                        srDC.RoundedDuration = srDC.GroupRoundedDuration.Value;
                    }

                    if (srDC.GroupOid != null)
                    {
                        groupBookingDict.Add(sr.GroupOid.Value, sr);
                    }

                    if (sr.CostBearer2SupportConceptOid != null && sr.CustomerOid != null)
                    {
                        FLSAnalysisGroupDC groupDC = null;

                        if (flsGroupDict.ContainsKey(sr.CustomerOid.Value))
                        {
                            groupDC = flsGroupDict[sr.CustomerOid.Value];
                        }

                        if (groupDC == null)
                        {
                            groupDC = new FLSAnalysisGroupDC();
                            groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                            flsGroupDict.Add(sr.CustomerOid.Value, groupDC);

                            // Customer c = null;
                            // if (customerDict.ContainsKey(sr.CustomerOid.Value))
                            // c = customerDict[sr.CustomerOid.Value];
                            Customer c = sr.Customer;

                            if (c != null)
                            {
                                groupDC.Customer = this.CreateCompactCustomerDC(c);


								if (config.Text1 != null || config.Text2 != null || config.Text3 != null || config.Text4 != null || config.Text5 != null)
                                {
                                    //if (MultitenancyOperationContextExt.Current.Tenant == )
                                    if (varFieldDefs == null)
                                    {
                                        varFieldDefs = new Dictionary<long, string>();
                                        IList<VarFieldDef> defs = DAOFactory.SearchDAO.GetVarFieldDefs(TableID.Customer);

                                        foreach (var def in defs)
                                        {
                                            varFieldDefs[def.Oid.Value] = def.Label;
                                        }
                                    }

                                    IList<VarFieldValue> varValues = c.VarFieldValueList;
                                    if (varValues != null && varValues.Count > 0)
                                    {
                                        foreach (var item in varValues)
                                        {
                                            Type type = Type.GetType(item.TypeName);
                                            object obj = BS.Shared.Core.Utils.XMLDeserializeFromString(item.SerializedValue, type);
                                            if (obj != null)
                                            {
                                                groupDC.Customer.VarFieldValues[item.VarFieldDefOid.Value] = obj.ToString();
                                            }
                                        }
                                    }

                                    groupDC.Customer.VarFieldDefs = varFieldDefs;
                                }
                            }

                            rootDC.Groups.Add(groupDC);
                        }

                        SupportConceptFLSOverviewDC scDC = null;
                        if (supportConceptOverviewDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                        {
                            scDC = supportConceptOverviewDict[sr.CostBearer2SupportConceptOid.Value];
                        }

                        if (scDC == null)
                        {
                            scDC = new SupportConceptFLSOverviewDC();
                            supportConceptOverviewDict.Add(sr.CostBearer2SupportConceptOid.Value, scDC);

                            // CostBearer2SupportConcept c2s = null;
                            // if(c2sDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                            // c2s = c2sDict[sr.CostBearer2SupportConceptOid.Value];
                            CostBearer2SupportConcept c2s = sr.CostBearer2SupportConcept;
                            if (c2s != null)
                            {
                                scDC.SupportConcept2CostBearer = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
                            }

                            groupDC.SupportConcepts.Add(scDC);
                        }

                        scDC.ServiceRecords.Add(srDC);
                    }
                    else
                    {
                        if (otherDC == null)
                        {
                            otherDC = new SupportConceptFLSOverviewDC();
                            FLSAnalysisGroupDC groupDC = new FLSAnalysisGroupDC();
                            groupDC.SupportConcepts = new List<SupportConceptFLSOverviewDC>();
                            rootDC.Groups.Add(groupDC);
                            groupDC.SupportConcepts.Add(otherDC);
                        }

                        otherDC.ServiceRecords.Add(srDC);
                    }
                }
            }

            return rootDC;
        }

        // private Dictionary<SupportConceptApprovalPeriod, DateTimeSpan> GetPeriodSpans(CostBearer2SupportConcept iCb2Sc)
        // {
        // var result = new Dictionary<SupportConceptApprovalPeriod, DateTimeSpan>();

        // var ordered = iCb2Sc.ApprovalPeriodList.Where(i => i.EndDate.HasValue).OrderBy(i => i.EndDate).ToList();
        // ordered.Add(iCb2Sc.ApprovalPeriodList.Single(i => !i.EndDate.HasValue));

        // var currentStart = iCb2Sc.ApprovedStartDate.Value;

        // foreach (var iPeriod in ordered)
        // {
        // var end = iPeriod.EndDate.HasValue
        // ? iPeriod.EndDate.Value
        // : iCb2Sc.ApprovedEndDate.Value;
        // result.Add(iPeriod, new DateTimeSpan
        // {
        // StartDateTime = currentStart, 
        // EndDateTime = end
        // });
        // currentStart = end;
        // }

        // return result;
        // }

        private decimal GetTotalAmount(CostBearer2SupportConcept cb2sc)
        {
			var calc = PluginLoader.FindClass<Calculations>(cb2sc.CostBearer.ID) ?? Calculations.GetInstance(cb2sc.CostBearer.ID);

            return calc.GetApprovedAmountTotal(cb2sc.MapToNewDC()) ?? 0m;

            // decimal amount = 0;

            // if (cb2sc != null)
            // {
            // CostBearer2SupportConceptData data = new CostBearer2SupportConceptData();
            // data.RequestedStartDate = cb2sc.RequestedStartDate;
            // data.RequestedEndDate = cb2sc.RequestedEndDate;
            // data.ApprovedStartDate = cb2sc.ApprovedStartDate;
            // data.ApprovedEndDate = cb2sc.ApprovedEndDate;
            // data.MonthlyPayment = cb2sc.MonthlyPayment;
            // //data.ApprovedFLS = cb2sc.ApprovedFLS;
            // //data.ApprovedFLSTotal = cb2sc.ApprovedFLSTotal;

            // if (cb2sc.CostBearer != null)
            // {
            // // data.IsCalculatingWithFactor = cb2sc.CostBearer.IsCalculatingWithFactor;
            // }

            // List<CostRate> crList = new List<CostRate>();
            // foreach (var item in cb2sc.CostBearer.CostRatePeriods)
            // {
            // CostRate cr = new CostRate();

            // cr.Amount = item.CostRateValue;
            // cr.CostRateType = (CostRateType)item.CostRateType;
            // cr.EndDate = item.EndDate;
            // cr.StartDate = item.StartDate;
            // crList.Add(cr);
            // }

            // data.CostRateList = crList;
            // amount = CostRateCalculationService.GetAmountTotal(data);
            // }
            // return amount;
        }

        private bool IsServiceRecordForGoal(ServiceRecord sr, List<long> goalOids)
        {
            if (goalOids == null)
            {
                return true;
            }

            if (goalOids.Count == 0)
            {
                return true;
            }

            foreach (var v2o in sr.ValueList)
            {
				if (v2o.Entry.Type == ValueListEntryType.SupportConceptGoalType || v2o.Entry.Type == ValueListEntryType.SupportConceptGoalCategoryType || v2o.Entry.Type == ValueListEntryType.SupportConceptIndividualGoalType || v2o.Entry.Type == ValueListEntryType.SupportConceptIndividualGoalCategoryType)
                {
                    foreach (var oid in goalOids)
                    {
                        if (v2o.Entry.Oid.Value == oid)
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }

        private ServiceRecordFLSOverviewDC CreateServiceRecordFLSOverviewDC(ServiceRecord sr, bool useGroupInfo, bool useRoundedDuration)
        {
            ServiceRecordFLSOverviewDC srDC = new ServiceRecordFLSOverviewDC();

            srDC.Start = sr.Start;
            srDC.End = sr.End;
	        srDC.DistanceInMeter = sr.DistanceInMeter;
            srDC.Notice = sr.Notice;
			
	        if (useRoundedDuration)
	        {
		        srDC.RoundedDuration = sr.RoundedDuration;
	        }
	        else
	        {
				srDC.RoundedDuration = (decimal)sr.End.Value.Subtract(sr.Start.Value).TotalMinutes;
	        }
	        if (sr.ServiceDescription != null)
                srDC.ServiceDescription = MapperFactory.ServiceDescriptionDC_ServiceDescription.MapToNewDC(sr.ServiceDescription);

            srDC.ServiceRecordOid = sr.Oid;
            srDC.EmployeeOid = sr.EmployeeOid;
            srDC.CustomerOid = sr.CustomerOid;
            srDC.CostBearer2SupportConceptOid = sr.CostBearer2SupportConceptOid;

            if (useGroupInfo)
            {
                srDC.GroupEmployeeCount = sr.GroupEmployeeCount;
                srDC.GroupPersonCount = sr.GroupPersonCount;
                srDC.GroupRoundedDuration = sr.GroupRoundedDuration;
                srDC.GroupOid = sr.GroupOid;
            }
            return srDC;
        }

        public List<AuslastungAnalysisRootDC> GetAuslastungAnalysis(DateTime? startDate, DateTime? endDate, long? employeeOid, long? teamOid)
        {
            try
            {
                var lResult = new List<AuslastungAnalysisRootDC>();

				var settings = AppSettings.CreateSettings();

                AuslastungAnalysisRootDC root = new AuslastungAnalysisRootDC();
                root.StartDate = startDate;
                root.EndDate = endDate;
                lResult.Add(root);

                if (teamOid.HasValue)
                {
                    Team team = DAOFactory.GenericDAO.LoadByID<Team>(teamOid.Value);

                    root.Team = MapperFactory.CompactTeamDC_Team.MapToNewDC(team);
                    foreach (var item in team.MemberList)
                    {
                        var a = CreateEmployeeAuslastung(item, startDate, endDate, settings.ShowRoundedDurationInEmployeeAnalysis);
                        root.EmployeeAnalysisList.Add(a);
                        root.TotalFLM += a.TotalFLM;
                    }


                }
                else if (employeeOid.HasValue)
                {
                    var emp = DAOFactory.GenericDAO.LoadByID<Employee>(employeeOid.Value);

					root.EmployeeAnalysisList.Add(CreateEmployeeAuslastung(emp, startDate, endDate, settings.ShowRoundedDurationInEmployeeAnalysis));
                }
                else
                {
                    IList<Employee> list = DAOFactory.GenericDAO.GetAllActive<Employee>();

                    foreach (var emp in list)
                    {
						root.EmployeeAnalysisList.Add(CreateEmployeeAuslastung(emp, startDate, endDate, settings.ShowRoundedDurationInEmployeeAnalysis));
                    }

                }
                if (root.EmployeeAnalysisList.Count > 1)
                    root.EmployeeAnalysisList.Sort((a, b) => (a.EmployeeLastName + ", " + a.EmployeeFirstName).CompareTo(b.EmployeeLastName + ", " + b.EmployeeFirstName));
                return lResult;
            }
            catch (Exception e)
            {
                throw (BeWo.Service.Core.Utils.CreateBeWoFaultException(e));
            }
        }

        private AuslastungAnalysisEmployeeDC CreateEmployeeAuslastung(Employee emp, DateTime? startDate, DateTime? endDate, bool useRoundedDuration)
        {
            AuslastungAnalysisEmployeeDC empDC = new AuslastungAnalysisEmployeeDC();
            empDC.EmployeeOid = emp.Oid;
            empDC.EmployeeFirstName = emp.Person.FirstName;
            empDC.EmployeeLastName = emp.Person.LastName;

            Contract contract = emp.LastContract;
            if (contract != null && contract.WeeklyFLS.HasValue)
                empDC.WeeklyTotalHours = contract.WeeklyTotalHours;

            IList<ServiceRecord> serviceRecords = null;

            if (startDate != null && endDate != null)
            {
                var span = new DateTimeSpan();
                span.StartDateTime = startDate.Value;
                span.EndDateTime = endDate.Value;
                serviceRecords = DAOFactory.SearchDAO.FindEmployeeServiceRecords(emp.Oid.Value, span, null, null);
            }
            else
            {
                serviceRecords = emp.ServiceRecordList;
            }

            //supportconcepts by costbearer2supportconceptoid
            Dictionary<long, AuslastungAnalysisSupportConceptDC> supportConceptDict = new Dictionary<long, AuslastungAnalysisSupportConceptDC>();
            if (emp.Employee2CustomerList != null)
            {
                foreach (Employee2Customer e2c in emp.Employee2CustomerList)
                {
                    bool isMainAttendant = false;
                    if (e2c.ValueList.Count > 0)
                    {
                        SystemEntryID? id = e2c.ValueList[0].Entry.SystemEntryID;
                        if (id.HasValue && id.Value == SystemEntryID.EmployeeRoleMainAttendant)
                            isMainAttendant = true;
                    }
                    if (isMainAttendant && e2c.Customer != null)
                    {
                        if (e2c.Customer.IsActive != ActivationTypeId.Deleted && e2c.Customer.SupportConcepts != null)
                        {
                            foreach (SupportConcept sc in e2c.Customer.SupportConcepts)
                            {
                                if (sc.IsActive != ActivationTypeId.Deleted && sc.CostBearer2SupportConceptList != null)
                                {
                                    foreach (CostBearer2SupportConcept cb2sc in sc.CostBearer2SupportConceptList)
                                    {
                                        bool inTimeRange = true;

                                        if (startDate.HasValue && endDate.HasValue)
                                        {
                                            DateTime? start = cb2sc.ApprovedStartDate;
                                            if (!start.HasValue)
                                                start = cb2sc.RequestedStartDate;

                                            DateTime? end = cb2sc.ApprovedEndDate;
                                            if (!end.HasValue)
                                                end = cb2sc.RequestedEndDate;
                                            if (start.HasValue && end.HasValue)
                                            {
                                                if (start > endDate || end < startDate)
                                                {
                                                    inTimeRange = false;
                                                }
                                            }
                                        }
                                        if (inTimeRange && !supportConceptDict.ContainsKey(cb2sc.Oid.Value))
                                        {

                                            //if (scStartDate == null || scEndDate == null || ())
                                            AuslastungAnalysisSupportConceptDC scDC = new AuslastungAnalysisSupportConceptDC();
                                            scDC.ServiceRecords = new List<ServiceRecordFLSOverviewDC>();
                                            supportConceptDict.Add(cb2sc.Oid.Value, scDC);
                                            CompactCustomerDC cdc = CreateCompactCustomerDC(e2c.Customer);
                                            scDC.CustomerOid = cdc.CustomerOid;
                                            scDC.CustomerFirstName = cdc.FirstName;
                                            scDC.CustomerLastName = cdc.LastName;

                                            scDC.CostBearer2SupportConcept = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(cb2sc);
                                            empDC.SupportConceptAnalysisList.Add(scDC);
                                        }
                                        else
                                        {
                                            //AuslastungAnalysisSupportConceptDC scDCTemp = new AuslastungAnalysisSupportConceptDC();

                                            //scDCTemp.Customer = CreateCompactCustomerDC(e2c.Customer);
                                            //scDCTemp.CostBearer2SupportConcept = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(cb2sc);


                                            //AuslastungAnalysisSupportConceptDC scDC2 = supportConceptDict[cb2sc.Oid.Value];

                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }


            AuslastungAnalysisSupportConceptDC otherDC = null;
            Dictionary<long, ServiceRecord> groupBookingDict = new Dictionary<long, ServiceRecord>();
            foreach (ServiceRecord sr in serviceRecords)
            {
                bool cont = true;
                if (sr.Customer != null && sr.Customer.IsActive == ActivationTypeId.Deleted)
                    cont = false;
                if (cont && sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
                    cont = false;

                if (cont && sr.GroupOid != null && groupBookingDict.ContainsKey(sr.GroupOid.Value))
                    cont = false;

                if (cont)
                {
                    ServiceRecordFLSOverviewDC srDC = CreateServiceRecordFLSOverviewDC(sr, true, useRoundedDuration);

                    if (srDC.GroupOid != null)
                    {
                        groupBookingDict.Add(sr.GroupOid.Value, sr);
                    }

                    if (sr.CostBearer2SupportConceptOid != null && sr.CustomerOid != null)
                    {
                        AuslastungAnalysisSupportConceptDC scDC = null;
                        if (supportConceptDict.ContainsKey(sr.CostBearer2SupportConceptOid.Value))
                        {
                            scDC = supportConceptDict[sr.CostBearer2SupportConceptOid.Value];

                            //if (scDC == null)
                            //{

                            //scDC = new AuslastungAnalysisSupportConceptDC();
                            //supportConceptDict.Add(sr.CostBearer2SupportConceptOid.Value, scDC);

                            //Customer c = sr.Customer;
                            //if (c != null)
                            //{
                            //    scDC.Customer = CreateCompactCustomerDC(c);
                            //}

                            //CostBearer2SupportConcept c2s = sr.CostBearer2SupportConcept;
                            //if (c2s != null)
                            //{
                            //    scDC.CostBearer2SupportConcept = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
                            //}


                            //empDC.SupportConceptAnalysisList.Add(scDC);

                            //}
                            scDC.ServiceRecords.Add(srDC);
                        }
                    }
                    else
                    {
                        if (otherDC == null)
                        {
                            otherDC = new AuslastungAnalysisSupportConceptDC();
                            otherDC.ServiceRecords = new List<ServiceRecordFLSOverviewDC>();

                        }
                        otherDC.ServiceRecords.Add(srDC);
                    }
                }

            }

            empDC.SupportConceptAnalysisList.Sort((a, b) => (a.CustomerLastName + ", " + a.CustomerFirstName).CompareTo(b.CustomerLastName + ", " + b.CustomerFirstName));

            if (otherDC != null)
                empDC.SupportConceptAnalysisList.Add(otherDC);
            return empDC;
        }

        public List<AnnualReportDC> CreateAnnualReport(long? costbearerOid, long? teamOid, long? customerCareTypeValueListEntryOid, DateTime startDate, DateTime endDate)
        {
            try
            {

	            AnnualReportFactory factory = null;
                CostBearer cb = null;
                if (costbearerOid.HasValue)
                {
                    cb = DAOFactory.GenericDAO.LoadByID<CostBearer>(costbearerOid.Value);

	                factory = PluginLoader.FindClass<AnnualReportFactory>(cb.ID) ?? AnnualReportFactory.GetInstance(cb.ID);
                }
                if (factory == null)
                {
                    factory = PluginLoader.FindClass<AnnualReportFactory>() ?? new AnnualReportFactory();
                }
                return factory.CreateAnnualReport(cb, teamOid, customerCareTypeValueListEntryOid, startDate, endDate);
            }
            catch (Exception e)
            {
                throw Utils.CreateBeWoFaultException(e);
            }
        }

        public static bool IsServiceRecordActive(ServiceRecord sr)
        {
            if (sr.Customer != null && sr.Customer.IsActive == ActivationTypeId.Deleted)
            {
                return false;
            }

            if (sr.SupportConcept != null && sr.SupportConcept.IsActive == ActivationTypeId.Deleted)
            {
                return false;
            }

            return true;
        }

        public static IList<ServiceRecord> FilterActiveServiceRecords(IList<ServiceRecord> records)
        {
            return records.Where(sr => IsServiceRecordActive(sr)).ToList();
        }

        public AccountingReportDC CreateAccountingReport(DateTime start, DateTime end)
        {
            var report = new AccountingReportDC
                {
                    AccountingReportRows = new List<AccountingReportRowDC>(),
                    StartDate = start,
                    EndDate = end
                };

            var span = new DateTimeSpan {StartDate = start, EndDate = end.AddDays(1).AddTicks(-1)};

            var serviceRecords = DAOFactory.SearchDAO.FindServiceRecordsInSpan(span, null);

            var rowDict = new Dictionary<long, AccountingReportRowDC>();

            foreach (var serviceRecord in serviceRecords)
            {

                if (serviceRecord.CostBearer2SupportConceptOid.HasValue)
                {
                    AccountingReportRowDC row = null;
                    if (rowDict.ContainsKey(serviceRecord.CostBearer2SupportConceptOid.Value))
                    {
                        row = rowDict[serviceRecord.CostBearer2SupportConceptOid.Value];
                    }
                    else
                    {
                        row = new AccountingReportRowDC();
                        rowDict.Add(serviceRecord.CostBearer2SupportConceptOid.Value, row);
                        row.Customer = MapperFactory.CompactCustomerDC_Customer.MapToNewDC(serviceRecord.Customer);

                        row.SupportConceptStart = serviceRecord.SupportConcept.StartDate;
                        row.SupportConceptEnd = serviceRecord.SupportConcept.EndDate;

                        CostBearer2SupportConcept cb2sc = serviceRecord.CostBearer2SupportConcept;
                        var costBearer = new CompactCostBearerDC
                            {
                                IsCalculatingWithFactor = cb2sc.CostBearer.IsCalculatingWithFactor,
                                CostBearerID = cb2sc.CostBearer.ID,
                                CostBearerOid = cb2sc.CostBearer.Oid.Value,
                                CostBearer2SupportConceptOid = cb2sc.Oid.Value,
                                SupportConceptStatus = cb2sc.Status,
                                RequestedStartDate = cb2sc.RequestedStartDate,
                                RequestedEndDate = cb2sc.RequestedEndDate,
                                ApprovedStartDate = cb2sc.ApprovedStartDate,
                                ApprovedEndDate = cb2sc.ApprovedEndDate,
                                Organisation =
                                    MapperFactory.CompactOrganisationDC_Organisation.MapToNewDC(
                                        cb2sc.CostBearer.Organisation)
                            };

                        row.CostBearer = costBearer;

                        report.AccountingReportRows.Add(row);
                    }

                    row.TotalDuration += serviceRecord.RoundedDuration;
                }
            }
            return report;
        }
    }
}