using System;
using System.Collections.Generic;
using System.Linq;

using BeWo.Core.Service;
using BeWo.ServiceProxy;
using BeWo.Scheduler.ViewModel;
using BeWo.ViewModel.ListViewModel;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using DevExpress.XtraPrinting.Native;


namespace BeWo.ViewModel
{
    public static class VMFactory
    {
        public static void CreateAbsenceReasonListVMAsync(Action<AbsenceReasonListVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.GetAllAbsenceReasons(), r => pCallBack(new AbsenceReasonListVM(r)));
        }

        public static void CreateAbsenceTimeListVMAsync(IEnumerable<AbsenceTimeDC> pDCs, Action<AbsenceTimeListVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.GetAllAbsenceReasons(), cb => pCallBack(new AbsenceTimeListVM(pDCs, cb)));
        }

		public static AbsenceTimeListVM CreateAbsenceTimeListVM(IEnumerable<AbsenceTimeDC> pDCs)
		{
			var list = ServiceFacade.DoCustomerServiceSync(s => s.GetAllAbsenceReasons());

			return new AbsenceTimeListVM(pDCs, list);
		}

	    public static void CreateOvertimeListVMAsync(IEnumerable<OvertimeDC> pDCs, Action<OvertimeListVM> pCallBack)
	    {
			//ServiceFacade.DoValueListServiceAsync(v => v.GetAllValueListEntrysByType(ValueListEntryType.Auszahlungsart), cb => pCallBack(new OvertimeListVM(pDCs)));
			ServiceFacade.DoEmployeeServiceAsync(v => v.GetAllOvertimes(), cb => pCallBack(new OvertimeListVM(pDCs)));
	    }

        public static void CreateAccountingBookingVMAsnyc(Action<AccountingBookingVM> pCallBack)
        {
            Cache.GetInstance().GetSupportConceptTree(
				tree => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(ValueListEntryType.AccountingTransactionType, categories => pCallBack(new AccountingBookingVM(tree, categories))));
        }

        public static void CreateAccountingTransactionListVMAsnyc(DateTimeSpan pSpan, long? pSupportConceptOid, long? pCostBearerSupportConceptRelOid, Action<AccountingTransactionListVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(s => s.GetAccountingTransactions(pSpan, pSupportConceptOid, pCostBearerSupportConceptRelOid), r => pCallBack(new AccountingTransactionListVM(r)));
        }

        public static void CreateAssessmentSheetCategoryListVM(Action<AssessmentSheetCategoryListVM> cb)
        {
            ServiceFacade.DoEmployeeServiceAsync(
                s1 => s1.GetAllAssessmentSheetValues(), v => ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllAssessmentSheetCategories(), dcs => cb(new AssessmentSheetCategoryListVM(dcs, v))));
        }

        public static void CreateAssessmentSheetValueListVM(Action<AssessmentSheetValueListVM> cb)
        {
            ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllAssessmentSheetValues(), dcs => cb(new AssessmentSheetValueListVM(dcs)));
        }

        public static void CreateBookingVMAsync(DateTimeSpan pSpan, Action<BookingVM> pCallBack)
        {
            ServiceFacade.DoResourceServiceAsync(s => s.GetAllBookings(pSpan.StartDateTime, pSpan.EndDateTime), r => pCallBack(new BookingVM(r)));
        }

		public static CustomerEmployeeRelationListVM CreateCustomerEmployeeRelationListVM(List<CustomerEmployeeRelationDC> pList)
        {
			var valueList = Cache.GetInstance().GetAllValueListEntrysByTypeSync(ValueListEntryType.StaffRoleType);
			return new CustomerEmployeeRelationListVM(pList, valueList);
        }

        public static WohnheimEmployeeRelationListVM CreateWohnheimEmployeeRelationListVM(List<WohnheimEmployeeRelationDC> pList)
        {
            var valueList = Cache.GetInstance().GetAllValueListEntrysByTypeSync(ValueListEntryType.StaffRoleType);
            return new WohnheimEmployeeRelationListVM(pList, valueList);
        }

        public static WohnheimCustomerRelationListVM CreateWohnheimCustomerRelationListVM(List<WohnheimCustomerRelationDC> pList)
        {
            var valueList = Cache.GetInstance().GetAllValueListEntrysByTypeSync(ValueListEntryType.StaffRoleType);
            return new WohnheimCustomerRelationListVM(pList, valueList);
        }

        public static void CreateOrganisationPersonRelationListVMAsync(List<OrganisationPersonRelationDC> pDCs, Action<OrganisationPersonRelationListVM> pCallBack)
        {
            pCallBack(new OrganisationPersonRelationListVM(pDCs));
        }

		public static CustomerPersonRelationListVM CreateCustomerEnvironmentPersonRelListVM(List<CustomerPersonRelationDC> pList)
        {
			var valueList = Cache.GetInstance().GetAllValueListEntrysByTypeSync(ValueListEntryType.EnvironmentPersonType);

			return new CustomerPersonRelationListVM(pList, valueList);
        }

        public static void CreateCustomerEnvironmentOrganisationRelListVMAsync(List<CustomerOrganisationRelationDC> pList, Action<CustomerOrganisationRelationListVM> pCallBack)
        {
			Cache.GetInstance().GetAllValueListEntrysByTypeAsync(ValueListEntryType.EnvironmentOrganisationType, r => pCallBack(new CustomerOrganisationRelationListVM(pList, r)));
        }

		public static CustomerOrganisationRelationListVM CreateCustomerEnvironmentOrganisationRelListVM(List<CustomerOrganisationRelationDC> pList)
		{
			var valueList = Cache.GetInstance().GetAllValueListEntrysByTypeSync(ValueListEntryType.EnvironmentOrganisationType);

			return new CustomerOrganisationRelationListVM(pList, valueList);
		}

	    public static MedikamentenverordnungslisteListVM CreateMedikementenverordnungslisteListVM(IEnumerable<MedikamentenverordnungslisteDC> pList)
	    {
		    var darreichungsformen = ServiceFacade.DoCustomerServiceSync(s => s.GetAllDarreichungsformen());
			var depotrhythmen = ServiceFacade.DoCustomerServiceSync(s => s.GetAllDepotRhythmen());

			return new MedikamentenverordnungslisteListVM(pList, darreichungsformen, depotrhythmen);
	    }

	    public static BargeldtransaktionsListVM CreateBargeldtransaktionsListVM(IEnumerable<BargeldtransaktionDC> pList)
	    {
		    return new BargeldtransaktionsListVM(pList);
	    }

        public static void CreateCustomerVMAsync(long pOid, Action<CustomerVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.LoadCustomer(pOid), cb => CreateCustomerVMAsync(cb, pCallBack));
        }

        public static void CreateCustomerVMAsync(Action<CustomerVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(
                s => s.GetVarFieldDefs(TableID.Customer), 
                cb => CreateCustomerVMAsync(
                    new CustomerDC
                        {
                            CustomerVarFields = cb
                        }, 
                    pCallBack));
        }

        public static void CreateCustomerVMAsync(CustomerDC pCustomerDC, Action<CustomerVM> pCallBack)
        {
            if (BeWoApp.ICD10Diagnosis == null)
            {
                ServiceFacade.DoOperationsServiceAsync(
                    s => s.GetCompressedICD10Diagnosis(), 
                    st =>
                        {
                            st = Utils.Decompress(st);
                            var ds = st.Split(Environment.NewLine).ToDictionary(line => line.Substring(0, line.IndexOf(';')), line => line.Substring(line.IndexOf(';') + 1));

	                        BeWoApp.ICD10Diagnosis = ds;
                            InternalCreateCustomerVM(pCustomerDC, pCallBack);
                        });
            }
            else
            {
                InternalCreateCustomerVM(pCustomerDC, pCallBack);
            }
        }

        public static void CreateEmployeeVMAsync(long pOid, Action<EmployeeVM> pCallBack)
        {
            ServiceFacade.DoEmployeeServiceAsync(
                s => s.LoadEmployee(pOid), 
                r =>
                    {
                        CreateEmployeeVMAsync(r, pCallBack);
                    });
        }

        public static void CreateEmployeeVMAsync(EmployeeDC pEmployeeDC, Action<EmployeeVM> pCallBack)
        {
	        ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllEmploymentTypes(),
		        r1 =>
			        Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
				        ValueListEntryType.StaffQualificationsType,
				        r2 =>
					        Cache.GetInstance()
								.GetAllValueListEntrysByTypeAsync(ValueListEntryType.StaffActivityFocusType,
							        r3 =>
								        ServiceFacade.DoEmployeeServiceAsync(r4 => r4.GetAllAuszahlungsarten(),
									        r5 => pCallBack(new EmployeeVM(pEmployeeDC, r1, r2, r3, r5))))));
        }

        public static void CreateEmployeeVMAsync(Action<EmployeeVM> pCallBack)
        {
            CreateEmployeeVMAsync(new EmployeeDC(), pCallBack);
        }

        public static void CreateWohnheimVMAsync(long pOid, Action<WohnheimVM> pCallBack)
        {
            ServiceFacade.DoWohnheimServiceAsync(
                s => s.LoadWohnheim(pOid),
                r =>
                {
                    CreateWohnheimVMAsync(r, pCallBack);
                });
        }

        public static void CreateWohnheimVMAsync(WohnheimDC pWohnheimDC, Action<WohnheimVM> pCallBack)
        {
            pCallBack(new WohnheimVM(pWohnheimDC));
        }

        public static void CreateWohnheimVMAsync(Action<WohnheimVM> pCallBack)
        {
            CreateWohnheimVMAsync(new WohnheimDC(), pCallBack);
        }

        public static void CreateEquityInvoiceBaselListVMAsync(long supportconeptOid, Action<InvoiceBaseListVM> callback)
        {
            ServiceFacade.DoAccountingServiceAsync(
                s => s.GetInvoiceBasesForSupportConcept(InvoiceType.CustomerEquity, supportconeptOid), 
                r =>
                    {
                        r.Sort(
                            (dc1, dc2) =>
                                {
                                    if (dc2.InvoiceDate == null)
                                    {
                                        return -1;
                                    }

                                    if (dc1.InvoiceDate == null)
                                    {
                                        return 1;
                                    }

                                    return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                });
                        callback(new InvoiceBaseListVM(r));
                    });
        }

        public static void CreateGeneralInvoiceBaselListVMAsync(CompactCustomerDC customer, CompactOrganisationDC organisation, CompactPersonDC person, Action<InvoiceBaseListVM> callback)
        {
            if (organisation != null)
            {
                ServiceFacade.DoAccountingServiceAsync(
                    s => s.GetGeneralInvoiceBasesForOrganisation(organisation.OrganisationOid), 
                    r =>
                        {
                            r.Sort(
                                (dc1, dc2) =>
                                    {
                                        if (dc2.InvoiceDate == null)
                                        {
                                            return -1;
                                        }

                                        if (dc1.InvoiceDate == null)
                                        {
                                            return 1;
                                        }

                                        return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                    });
                            callback(new InvoiceBaseListVM(r));
                        });
            }
            else if (person != null)
            {
                ServiceFacade.DoAccountingServiceAsync(
                    s => s.GetGeneralInvoiceBasesForPerson(person.PersonOid), 
                    r =>
                        {
                            r.Sort(
                                (dc1, dc2) =>
                                    {
                                        if (dc2.InvoiceDate == null)
                                        {
                                            return -1;
                                        }

                                        if (dc1.InvoiceDate == null)
                                        {
                                            return 1;
                                        }

                                        return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                    });
                            callback(new InvoiceBaseListVM(r));
                        });
            }
            else if (customer != null)
            {
                ServiceFacade.DoAccountingServiceAsync(
                    s => s.GetGeneralInvoiceBasesForCustomer(customer.CustomerOid), 
                    r =>
                        {
                            r.Sort(
                                (dc1, dc2) =>
                                    {
                                        if (dc2.InvoiceDate == null)
                                        {
                                            return -1;
                                        }

                                        if (dc1.InvoiceDate == null)
                                        {
                                            return 1;
                                        }

                                        return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                    });
                            callback(new InvoiceBaseListVM(r));
                        });
            }
        }

        public static void CreateInvoiceListVMAsync(Action<InvoiceListVM> callback)
        {
            ServiceFacade.DoCustomerServiceAsync(
                s1 => s1.GetAllActiveSupportConceptsCompact(), 
                r1 =>
                ServiceFacade.DoCustomerServiceAsync(
                    s2 => s2.GetAllActiveOrganisationsCompact(), r2 => ServiceFacade.DoOperationsServiceAsync(s3 => s3.GetAllActiveInvoices(), r3 => callback(new InvoiceListVM(r2, r1, r3)))));
        }

        public static void CreateInvoiceNumberVMAsync(Action<InvoiceNumberVM> pCallBack)
        {
            ServiceFacade.DoAccountingServiceAsync(s => s.LoadInvoiceNumber(), r => pCallBack(new InvoiceNumberVM(r)));
        }

        public static void CreateInvoiceOverviewListVM(Action<InvoiceBaseListVM> callback)
        {
            ServiceFacade.DoAccountingServiceAsync(s => s.GetAllActiveInvoiceBases(), cb => callback(new InvoiceBaseListVM(cb)));
        }

        public static void CreateOrganisationVMAsync(long pOid, Action<OrganisationVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(
                s => s.LoadOrganisation(pOid),
				r1 => ServiceFacade.DoValueListServiceAsync(s1 => s1.GetAllValueListEntrysByType(ValueListEntryType.StaffQualificationsType), r2 => pCallBack(new OrganisationVM(r1, r2))));
        }

        public static void CreateOrganisationVMAsync(Action<OrganisationVM> pCallBack)
        {
			ServiceFacade.DoValueListServiceAsync(
				s1 => s1.GetAllValueListEntrysByType(ValueListEntryType.StaffQualificationsType), 
					r1 =>
					ServiceFacade.DoOperationsServiceAsync(
						s => s.GetVarFieldDefs(TableID.Organisation),
							r2 => pCallBack(new OrganisationVM(
								new OrganisationDC
								{
									VarFields = r2
								}, r1))));
        }

		//public static void CreatePersonOrganisationRelationVMAsync(CompactOrganisationDC pOrganisation, Action<PersonOrganisationRelationVM> pCallBack)
		//{
		//    pCallBack(
		//        new PersonOrganisationRelationVM(
		//            new Organisation2PersonDC
		//                {
		//                    OrganisationOid = pOrganisation.OrganisationOid, 
		//                    OrganisationName = pOrganisation.Name, 
		//                    OrganisationVersion = pOrganisation.OrganisationVersion
		//                }));
		//}

        public static void CreatePersonVMAsync(Action<PersonVM> pCallBack)
        {
			Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                ValueListEntryType.TitleType, 
                r1 =>
                ServiceFacade.DoOperationsServiceAsync(
                    s => s.GetVarFieldDefs(TableID.Person),
					r2 => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                        ValueListEntryType.FunctionType, 
                        r3 => pCallBack(
                            new PersonVM(
                                  new PersonDC
                                      {
                                          VarFields = r2
                                      }, 
                                  r1, 
                                  r3)))));
        }

        public static void CreatePersonVMAsync(long pOid, Action<PersonVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(
                s => s.LoadPerson(pOid), 
                cb =>
				Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
					ValueListEntryType.TitleType, r1 => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(ValueListEntryType.FunctionType, r2 => pCallBack(new PersonVM(cb, r1, r2)))));
        }

        public static void CreateResourceListVMAsync(Action<ResourceListVM> pCallBack)
        {
            ServiceFacade.DoResourceServiceAsync(
                s => s.GetAllResources(),
				r1 => ServiceFacade.DoValueListServiceAsync(s => s.GetAllValueListEntrysByType(ValueListEntryType.ResourceCategory), r2 => pCallBack(new ResourceListVM(r1, r2))));
        }

        public static void CreateServiceCategoryListVMAsync(Action<ServiceCategoryListVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(s => s.GetAllServiceCategories(),
                r => pCallBack(new ServiceCategoryListVM(r.Where(sc => sc.ScopeType == ScopeTypeId.Global).ToList())));
        }

		public static void CreateAdditionalServiceListVMAsync(Action<AdditionalServiceListVM> pCallBack)
		{
			ServiceFacade.DoOperationsServiceAsync(s => s.GetAllAdditionalService(),
				r => pCallBack(new AdditionalServiceListVM(r.ToList())));
		}

	    public static void CreateAuszahlungsartenListVMAsync(Action<AuszahlungsartListVM> pCallBack)
	    {
		    ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllAuszahlungsarten(), 
				r => pCallBack(new AuszahlungsartListVM(r.ToList())));
	    }

        public static void CreateTextbausteinListVMAsync(Action<TextbausteinListVM> pCallBack, bool pIsInAdministrationView = false)
        {
            ServiceFacade.DoOperationsServiceAsync(s1 => s1.GetAllTextbausteine(), r1 => ServiceFacade.DoOperationsServiceAsync(
                s2 => s2.GetAllServiceCategories(),
                    s3 =>
                    {
                        if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.TextbausteineAlleAnsehen))
                        {
                            r1 = r1.Where(w => w.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid)).ToList();
                        }

                        if (pIsInAdministrationView)
                        {
                            r1 = r1.Where(w => !w.IsOnlyForEmployee).ToList();
                        }

                        pCallBack(new TextbausteinListVM(r1, s3));
                    }));
        }

	    public static void CreateMedArtListVMAsync(Action<MedArtListVM> pCallBack)
	    {
		    ServiceFacade.DoCustomerServiceAsync(s => s.GetAllMedArten(),
			    r => pCallBack(new MedArtListVM(r.ToList())));
	    }

        public static void CreateServiceDescriptionListVMAsync(Action<ServiceDescriptionListVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(
                s1 => s1.GetAllServiceDescriptions(), r1 => ServiceFacade.DoOperationsServiceAsync(s2 => s2.GetAllServiceCategories(),
                    r2 => pCallBack(new ServiceDescriptionListVM(r1.Where(sr => sr.ScopeType == ScopeTypeId.Global).ToList(), r2.Where(sc => sc.ScopeType == ScopeTypeId.Global).ToList()))));
        }

		public static void CreateAdditionalServiceRegionListVMAsync(Action<AdditionalServiceRegionListVM> pCallBack)
		{
			ServiceFacade.DoOperationsServiceAsync(s1 => s1.GetAllAdditionalServiceRegion(), r1 => ServiceFacade.DoOperationsServiceAsync(s2 => s2.GetAllAdditionalService(), r2 => pCallBack(new AdditionalServiceRegionListVM(r1.ToList(), r2.ToList()))));
		}

        public static void CreateServiceRecordVMAsync(long pEmployeeOid, Action<ServiceRecordListVM> pCallBack)
        {
            Cache.GetInstance().GetServiceCategoryDescriptionDict(
                dict =>
                    Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                        ValueListEntryType.SupportConceptGoalCategoryType,
                        goalCats =>
                            Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                                ValueListEntryType.SupportConceptIndividualGoalCategoryType,
                                iGoalCats =>
                                    Cache.GetInstance().GetAllValueListEntrysByTypeAsync(ValueListEntryType.SupportConceptGoalType,
                                        goals => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(ValueListEntryType.DocumentType,
                                            docTypes => 
                                                ServiceFacade.DoCustomerServiceAsync(
                                                s => s.GetAllActiveWohnheimeCompact(), cb => ServiceFacade.DoCustomerServiceAsync(s2 => s2.GetAllDarreichungsformen(), abc => pCallBack(new ServiceRecordListVM(dict, goalCats, iGoalCats, goals, cb, docTypes, abc)))))))));
        }

        public static void CreateMedRecordVMAsync(long pCustomerOid, Action<MedRecordListVM> pCallback)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.GetMedRecordsForCustomer(pCustomerOid), cb => pCallback(new MedRecordListVM(cb)), true);
        }

        public static void CreateSettlementListForCostBearerAndPeriod(long costBearerOid, DateTime periodStart, DateTime periodEnd, Action<SettlementListVM> callback)
        {
            ServiceFacade.DoAccountingServiceAsync(
                s => s.GetSettlementInvoicesForCostBearerAndPeriod(costBearerOid, periodStart, periodEnd), 
                r =>
                    {
                        r.Sort(
                            (dc1, dc2) =>
                                {
                                    if (dc2.InvoiceDate == null)
                                    {
                                        return -1;
                                    }

                                    if (dc1.InvoiceDate == null)
                                    {
                                        return 1;
                                    }

                                    return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                });
                        callback(new SettlementListVM(r));
                    });
        }

        public static void CreateSettlementListForSupportConceptVMAsync(long supportconceptOid, Action<SettlementListVM> callback)
        {
            ServiceFacade.DoAccountingServiceAsync(
                s => s.GetSettlementInvoicesForSupportConcept(supportconceptOid), 
                r =>
                    {
                        r.Sort(
                            (dc1, dc2) =>
                                {
                                    if (dc2.InvoiceDate == null)
                                    {
                                        return -1;
                                    }

                                    if (dc1.InvoiceDate == null)
                                    {
                                        return 1;
                                    }

                                    return dc2.InvoiceDate.Value.CompareTo(dc1.InvoiceDate.Value);
                                });
                        callback(new SettlementListVM(r));
                    });
        }

        public static void CreateSettlementVMAsync(long pSupportConcept2CostBearerOid, Action<SettlementVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(s => s.GenerateInitialSettlementDC(pSupportConcept2CostBearerOid), r => pCallBack(new SettlementVM(r)));
        }

        public static void CreateSupportConceptCostBearerRelVMAsync(List<SupportConceptCostBearerRelDC> pList, Action<SupportConceptCostBearerRelListVM> pCallBack)
        {
            pCallBack(new SupportConceptCostBearerRelListVM(pList));
        }

        public static void CreateSupportConceptGoalListVMAsync(ValueListEntryType pType, ValueListEntryType pParentType, Action<SupportConceptGoalListVM> pCallBack)
        {
			Cache.GetInstance().GetAllValueListEntrysByTypeAsync(pType, r1 => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(pParentType, r2 => pCallBack(new SupportConceptGoalListVM(r1, r2))));
        }

        public static void CreateSupportConceptVMAsync(Action<SupportConceptVM> pCallback)
        {
            CreateSupportConceptVMAsync(new SupportConceptDC(), pCallback, true);
        }

        public static void CreateSupportConceptVMAsync(long pOid, Action<SupportConceptVM> pCallback)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.LoadSupportConcept(pOid), 
                r => CreateSupportConceptVMAsync(r, pCallback, false));
        }

        public static void CreateSupportConceptVMAsync(SupportConceptDC dc, Action<SupportConceptVM> pCallBack, bool initOriginator)
        {
			Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                ValueListEntryType.SupportConceptGoalCategoryType,
				r1 => Cache.GetInstance().GetAllValueListEntrysByTypeAsync(
                    ValueListEntryType.SupportConceptGoalType, 
                    r2 => Cache.GetInstance().GetServiceCategoryDescriptionDict(
                        dict =>
                        {
                            var vm = new SupportConceptVM(dc, r1, r2, dict);
                            if (initOriginator)
                            {
                                vm.Originator = BeWoApp.LoggedOnUser.Employee;
                            }

                            pCallBack(vm);
                        })));
        }

        public static void CreateTeamVMAsync(Action<TeamVM> pCallBack)
        {
            pCallBack(new TeamVM(new TeamDC()));
        }

        public static void CreateTeamVMAsync(long pTeamOid, Action<TeamVM> pCallBack)
        {
            ServiceFacade.DoEmployeeServiceAsync(s => s.LoadTeam(pTeamOid), cb => pCallBack(new TeamVM(cb)));
        }

        public static void CreateGroupOfPeopleVMAsync(Action<GroupOfPeopleVM> pCallBack)
        {
            pCallBack(new GroupOfPeopleVM(new GroupOfPeopleDC()));
        }

        public static void CreateGroupOfPeopleVMAsync(long pGroupOfPeopleOid, Action<GroupOfPeopleVM> pCallBack)
        {
            ServiceFacade.DoEmployeeServiceAsync(s => s.LoadGroupOfPeople(pGroupOfPeopleOid), cb => pCallBack(new GroupOfPeopleVM(cb)));
        }

        public static void CreateGroupOfPeopleListVMAsync(Action<GroupOfPeopleListVM> pCallBack)
        {
            ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllGroups(BeWoApp.LoggedOnEmployee.EmployeeOid), cb => pCallBack(new GroupOfPeopleListVM(cb)));
        }

        public static void CreateAdditinoalServiceGroupOfPeopleListVMAsync(Action<AdditionalServiceGroupOfPeopleListVM> pCallBack)
        {
            ServiceFacade.DoOperationsServiceAsync(s => s.GetAllAdditionalServiceGroupOfPeople(), cb => pCallBack(new AdditionalServiceGroupOfPeopleListVM(cb)));
        }

        public static void CreateUserGroupVMAsync(long pOid, Action<UserGroupVM> pCallBack)
        {
            ServiceFacade.DoUserServiceAsync(s => s.LoadUserGroup(pOid), r => pCallBack(new UserGroupVM(r)), true);
        }

        public static void CreateUserGroupVMAsync(Action<UserGroupVM> pCallBack)
        {
            pCallBack(new UserGroupVM(new UserGroupDC()));
        }

        public static void CreateUserVMAsync(long pUserOid, Action<UserVM> pCallBack)
        {
            ServiceFacade.DoUserServiceAsync(s => s.LoadUser(pUserOid), r1 => ServiceFacade.DoUserServiceAsync(s => s.GetAllUserGroups(), r2 => pCallBack(new UserVM(r1, r2)), true), true);
        }

        public static void CreateUserVMAsync(Action<UserVM> pCallBack)
        {
            ServiceFacade.DoUserServiceAsync(s => s.GetAllUserGroups(), cb => pCallBack(new UserVM(new UserDC(), cb)), true);
        }

        public static void CreateValueListVMAsync(ValueListEntryType pType, Action<ValueListEntryListVM> pCallBack)
        {
			ServiceFacade.DoValueListServiceAsync(s => s.GetAllValueListEntrysByType(pType), r => pCallBack(new ValueListEntryListVM(pType, r)));
        }

       

        public static void CreateGoalCategoryVMAsync(Action<GenericValueListEntryListVM> pCallBack, bool pIsIncludingIndividualGoals = false)
        {
            var typeList = new List<ValueListEntryType> { ValueListEntryType.SupportConceptGoalType, ValueListEntryType.SupportConceptGoalCategoryType };
            if (pIsIncludingIndividualGoals)
            {
                typeList.Add(ValueListEntryType.SupportConceptIndividualGoalCategoryType);
                typeList.Add(ValueListEntryType.SupportConceptIndividualGoalType);
            }

            ServiceFacade.DoValueListServiceAsync(
				s => s.GetAllValueListEntrysByTypes(typeList), 
                cb => pCallBack(new GenericValueListEntryListVM(cb)));
	    }

        public static void CreateEmploymentTypeListVMAsync(Action<EmploymentTypeListVM> pCallBack)
        {
            ServiceFacade.DoEmployeeServiceAsync(s => s.GetAllEmploymentTypes(), r => pCallBack(new EmploymentTypeListVM(r)));
        }

        private static void InternalCreateCustomerVM(CustomerDC pCustomerDC, Action<CustomerVM> pCallBack)
        {
            var list = new List<ValueListEntryType>
                {
                    ValueListEntryType.DisabilityType, 
                    ValueListEntryType.CustomerCareType, 
                    ValueListEntryType.PlacementObjectiveType, 
                    ValueListEntryType.TerminationReasonType
                };

	        ServiceFacade.DoValueListServiceAsync(
				s => s.GetAllValueListEntrysByTypes(list),
		        cb => ServiceFacade.DoEmployeeServiceAsync(s2 => s2.GetAllAssessmentSheetCategories(),
			        cb2 => ServiceFacade.DoEmployeeServiceAsync(s3 => s3.GetAllAssessmentSheetValues(),
				        cb3 => ServiceFacade.DoCustomerServiceAsync(s4 => s4.GetAllMedArten(),
					        cb4 => pCallBack(new CustomerVM(pCustomerDC, cb, cb2, cb3, cb4))))));
        }

		public static void CreateNewSchedulerAppointmentListVM(Action<SchedulerAppointmentListVM> pCallBack, DateTime intervalStart, DateTime intervalEnd)
		{
			if (!BeWoApp.LoggedOnEmployee.EmployeeOid.HasValue)
			{
			    return;
			}

			var allEmps          = new List<CompactEmployeeDC>();
			var allCats2ResInDic = new Dictionary<ValueListEntryDC, List<ResourceDC>>();
			var appointments     = new List<SchedulerAppointmentDC>();
			var allCust          = new List<CompactCustomerDC>();

			allEmps = Cache.GetInstance().GetAllActiveEmployeesCompactSync();

			if (!BeWoApp.LoggedOnUser.HasRight(UserRightType.EmployeeView_View) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen))
			{
				ServiceFacade.DoEmployeeServiceSync(es => allEmps = new List<CompactEmployeeDC> {es.LoadCompactEmployee(BeWoApp.LoggedOnEmployee.EmployeeOid.Value)});
			}

            ServiceFacade.DoResourceServiceSync(s => allCats2ResInDic = s.GetAllCategories2ResourcesInDictionary());

			ServiceFacade.DoResourceServiceSync(rs => appointments = rs.GetAllActiveAppointmentsForEmployeeInInterval2(intervalStart, intervalEnd, BeWoApp.LoggedOnEmployee.EmployeeOid.Value, BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)));

			allCust = Cache.GetInstance().GetAllActiveCustomersCompactSync();

			if (BeWoApp.LoggedOnUser.HasRight(UserRightType.Customer_ViewMyCustomers) && !BeWoApp.LoggedOnUser.HasRight(UserRightType.CustomerView_View))
			{
			    allCust = allCust.Where(c => BeWoApp.LoggedOnEmployee.RelatedCustomers.Any(a => a.Customer.Equals(c))).ToList();
			}

            var prefilteredAppointments = appointments.Where(w => ((w.EmployeeList.Count == 0 && w.Originator.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid) ||
                                              w.EmployeeList.Count > 0 && w.EmployeeList.Any(a => a.Employee.EmployeeOid.Equals(BeWoApp.LoggedOnEmployee.EmployeeOid))) ||
											  BeWoApp.LoggedOnUser.HasRight(UserRightType.KalenderMitarbeitertermineAnsehen)) && (!w.EmployeeList.TrueForAll(e2a => e2a.ParticipationAnswer == ParticipationAnswer.Absage) || w.EmployeeList.IsEmpty()));

			pCallBack(new SchedulerAppointmentListVM(prefilteredAppointments.ToList(), allCust, allEmps, allCats2ResInDic));
		}

        public static void CreateAppointmentCategoryListVMAsync(Action<AppointmentCategoryListVM> pCallBack)
        {
            ServiceFacade.DoCustomerServiceAsync(
                s => s.GetAllAppointmentCategories(), cats => pCallBack(new AppointmentCategoryListVM(cats)));
        }

        public static WohnheimbuchungEmployeeRelListVM CreateEmployeeWohnheimbuchungsListVM(IEnumerable<WohnheimbuchungEmployeeRelationDC> pList)
        {
            return new WohnheimbuchungEmployeeRelListVM(pList);
        }

        public static Wohnheimbuchung2Costbearer2SupportConceptRelListVM CreateSupportConceptWohnheimbuchungsListVM(IEnumerable<Wohnheimbuchung2Costbearer2SupportConceptRelationDC> pList)
        {
            return new Wohnheimbuchung2Costbearer2SupportConceptRelListVM(pList);
        }

        public static void CreateWohnheimbuchungsVMAsync(long? pOid, Action<WohnheimbuchungsVM> pCallBack)
        {
            Cache.GetInstance().GetServiceCategoryDescriptionDict(
                dict =>
                {
                    if (pOid == null)
                    {
                        pCallBack(new WohnheimbuchungsVM(new WohnheimbuchungDC(), dict));
                    }
                    else
                    {
                        ServiceFacade.DoCustomerServiceAsync(s => s.GetWohnheimbuchung(pOid.Value), cb => pCallBack(new WohnheimbuchungsVM(cb, dict)));
                    }
                });
        }

        public static SupportConceptApprovalPeriodEmployeeRelListVM CreateSupportConceptApprovalPeriodEmployeeRelListVM(IEnumerable<SupportConceptApprovalPeriodEmployeeRelDC> pList)
        {
            return new SupportConceptApprovalPeriodEmployeeRelListVM(pList);
        }
    }
}