using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Threading;

using BeWo.Core;
using BeWo.ServiceProxy;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;

namespace BeWo.ViewModel.ListViewModel
{
    public class ServiceRecordListVM : AbstractDCListMapperVM<ServiceRecordDC, ServiceRecordVM>
    {
        public static string PropertyName_CustomerNodes = "CustomerNodes";

        public static string PropertyName_Information = "Information";

        public static string PropertyName_PrototypeVM = "PrototypeVM";

        public static string PropertyName_RecordCountInformationString = "RecordCountInformationString";

        public static string PropertyName_RecordingDays = "RecordingDays";

        public static string PropertyName_ServiceRecordsForSelectedCustomer = "ServiceRecordsForSelectedCustomer";

        public static string PropertyName_IsCustomerWarningActive = "IsCustomerWarningActive";

        public static string PropertyName_CustomerWarning = "CustomerWarning";

        public static string PropertyName_Statistics = "Statistics";

        public static string PropertyName_ServiceRecordTimeInterval = "ServiceRecordTimeInterval";

        public static string PropertyName_Wohnheimbuchungen = "Wohnheimbuchungen";

        public static string PropertyName_SelectedWohnheimbuchung = "SelectedWohnheimbuchung";

        public static string PropertyName_BedarfsMedViewModel = "BedarfsMedViewModel";

        public static string PropertyName_MedRecordCreationEnabled = "MedRecordCreationEnabled";

        public event EventHandler StatisticInfosLoaded;

        private readonly List<ValueListEntryDC> _AllGoalCategories;

        private readonly Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> _Category2Services;

        private readonly Dictionary<long, SupportConceptTreeNodeDetailInfoDC> _CostBearer2SupportConceptOid2BookingInfoDict = new Dictionary<long, SupportConceptTreeNodeDetailInfoDC>();

        //private readonly Dictionary<String, long> _ServiceRecordsLoaded = new Dictionary<String, long>();

        //private readonly Dictionary<CompactEmployeeDC, bool> _EmployeeServiceRecordsLoaded = new Dictionary<CompactEmployeeDC, bool>();

        private readonly BindingList<ServiceRecordVM> _ServiceRecordsForSelectedCustomer;

        private List<ValueListEntryDC> _AllGoals;

        private ObservableSortCollection<FlatSupportConceptTreeNodeDC> _CustomerNodes;

        private ServiceRecordVM _PrototypeVM;

        private string _RecordCountInformationString;

        private ObservableCollection<DayOfWeek> _RecordingDays;

        private FlatSupportConceptTreeNodeDC _SelectedCustomerNode;

        private CompactEmployeeDC mSelectedEmployee;

        private bool _IsCustomerWarningActive;

        private string _CustomerWarning;

        private ServiceRecordTimeInterval _ServiceRecordTimeInterval = ServiceRecordTimeInterval.LastWeek;

        private bool _ShowOnlyContentServiceRecords;

        private List<SupportConceptPeriodStatisticsVM> _Statistics;

        private int _NDays;

        private WohnheimbuchungsVM selectedWohnheimbuchung;

        private static List<DarreichungsformDC> _AllDosageForms; 

        public ServiceRecordListVM(
            Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> pCategory2Services,
            IEnumerable<ValueListEntryDC> pAllGoalCategories,
            IEnumerable<ValueListEntryDC> pAllIndGoalCategories,
            List<ValueListEntryDC> pAllGoals,
            List<CompactWohnheimDC> pAlleWohnheime,
            List<ValueListEntryDC> allDocTypes,
            List<DarreichungsformDC> pAllDosageForms)
        {
            _ServiceRecordTimeInterval = BeWoApp.AppSettings.LastSelectedServiceRecordTimeInterval;
            _NDays = BeWoApp.AppSettings.NDays;

            if (pCategory2Services != null)
            {
                Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> globalCats =
                    pCategory2Services.Keys.Where(cat => cat.ScopeType == ScopeTypeId.Global)
                        .ToDictionary(cat => cat, cat => pCategory2Services[cat]);
                _Category2Services = globalCats;
            }

            _ServiceRecordsForSelectedCustomer = new BindingList<ServiceRecordVM>();

            

            

            var wdc = new WohnheimbuchungDC();
            wdc.Buchungsdatum = DateTime.Now;

            var gefilterteWohnheime =
                pAlleWohnheime.Where(wh => wh.EmployeeOids.Contains(BeWoApp.LoggedOnEmployee.EmployeeOid.Value)).ToList();
            if (gefilterteWohnheime.Count == 1)
            {
                wdc.Wohnheim = gefilterteWohnheime[0];
            }
            selectedWohnheimbuchung = new WohnheimbuchungsVM(wdc, pCategory2Services);

            AlleWohnheime = gefilterteWohnheime;

            AllDosageForms = pAllDosageForms;

            _AllGoalCategories = new List<ValueListEntryDC>();

	        if (pAllGoalCategories != null)
	        {
		        _AllGoalCategories.AddRange(pAllGoalCategories);
	        }
	        if (pAllIndGoalCategories != null)
	        {
		        _AllGoalCategories.AddRange(pAllIndGoalCategories);
	        }
	        _AllGoals = pAllGoals;
            AllDocTypes = allDocTypes;
			if (AllDocTypes != null)
			{
				AllDocTypes.Sort((a, b) => a.ValueListEntryOid.Value.CompareTo(b.ValueListEntryOid.Value));
			}
            VMList.ListChanged += (s, e) => CheckCustomerAbsenceTimes();
        }

        public bool MedRecordCreationEnabled
        {
            get { return (BeWoApp.LoggedOnUser.HasRight(UserRightType.MedRecordsAnlegen) || BeWoApp.LoggedOnUser.HasRight(UserRightType.CreateAll)) && BedarfsMedViewModel != null; }
        }

        public List<ValueListEntryDC> AllDocTypes { get; set; }
        //VMFactory.CreateCustomerVMAsync(pCustomerOID, cb => this.Dispatch(delegate { ViewModel = cb; UpdateUris(); }));
        
        public void LoadExistingWohnheimbuchung(CompactWohnheimDC pWohnheim, DateTime pBuchungsdatum, Action<bool> callback)
        {
            ServiceFacade.DoCustomerServiceAsync(s => s.GetWohnheimbuchungByWohnheimAndBuchungsdatum(pWohnheim.WohnheimOid, pBuchungsdatum), r =>
            {
                SelectedWohnheimbuchung = new WohnheimbuchungsVM(r ?? new WohnheimbuchungDC { Buchungsdatum = pBuchungsdatum, Wohnheim = pWohnheim }, PrototypeVM.Category2Services) { Category = selectedWohnheimbuchung.Category, ServiceDescription = selectedWohnheimbuchung.ServiceDescription };

                if (r == null)
                {
                    SelectedWohnheimbuchung.Wohnheimbuchung2Costbearer2SupportConceptList = new Wohnheimbuchung2Costbearer2SupportConceptRelListVM(SelectedWohnheimbuchung.DataContract.Costbearer2SupportConceptList);
                    SelectedWohnheimbuchung.EmployeeList                                  = new WohnheimbuchungEmployeeRelListVM(SelectedWohnheimbuchung.DataContract.EmployeeList);
                    SelectedWohnheimbuchung.Buchungsdatum                                 = pBuchungsdatum;
                    SelectedWohnheimbuchung.Wohnheim                                      = pWohnheim;
                    selectedWohnheimbuchung.Category                                      = selectedWohnheimbuchung.Category;
                    selectedWohnheimbuchung.ServiceDescription                            = selectedWohnheimbuchung.ServiceDescription;
                }
                else
                {
                    var serviceDescription = ServiceFacade.DoCustomerServiceSync(s => s.FindServiceDescriptionForWohnheimbuchungsServiceRecord(r.WohnheimbuchungOid.Value)) ?? selectedWohnheimbuchung.ServiceDescription;

                    selectedWohnheimbuchung.ServiceDescription = serviceDescription;
                    selectedWohnheimbuchung.Category           = serviceDescription.Category;
                }

                callback(r != null);
            });
        }

        private MedRecordListVM _BedarfsMedViewModel;

        public MedRecordListVM BedarfsMedViewModel
        {
            get { return _BedarfsMedViewModel; }

            set
            {
                _BedarfsMedViewModel = value;
                FirePropertyChanged(PropertyName_BedarfsMedViewModel);
                FirePropertyChanged(PropertyName_MedRecordCreationEnabled);
            }
        }

        public static List<DarreichungsformDC> AllDosageForms { get; private set; }

        public WohnheimbuchungsVM SelectedWohnheimbuchung
        {
            get { return selectedWohnheimbuchung; }
            set
            {
                selectedWohnheimbuchung = value;
                FirePropertyChanged(PropertyName_SelectedWohnheimbuchung);
            }
        }

        public List<CompactWohnheimDC> AlleWohnheime { get; private set; }

        public int NDays
        {
            get { return _NDays; }

            set
            {
                if (_NDays != value)
                {
                    _NDays = value;
                    ServiceRecordTimeInterval = ServiceRecordTimeInterval.LastNDays;
                    BeWoApp.AppSettings.NDays = value;
                    BeWoApp.SaveAppSettings();
                }
            }
        }

        public List<SupportConceptPeriodStatisticsVM> Statistics
        {
            get { return _Statistics; }
            set
            {
                _Statistics = value;
                FirePropertyChanged(PropertyName_Statistics);
                FirePropertyChanged("HasStatistics");
            }
        }

        public bool HasStatistics
        {
            get { return _Statistics != null && _Statistics.Count > 0; }
        }

        public ServiceRecordTimeInterval ServiceRecordTimeInterval
        {
            get { return _ServiceRecordTimeInterval; }
            set
            {
                if (_ServiceRecordTimeInterval != value)
                {
                    _ServiceRecordTimeInterval = value;
                    BuildServiceRecordsForSelectedTreeNode(true);
                    BeWoApp.AppSettings.LastSelectedServiceRecordTimeInterval = value;
                    BeWoApp.SaveAppSettings();
                    FirePropertyChanged(PropertyName_ServiceRecordTimeInterval);
                }
            }
        }

        public ServiceRecordTypeId? OnlyWithThisType { get; set; }
        private bool _ShowOnlyAdditionalServiceRecords;

        public bool ShowOnlyAdditionalServiceRecords
        {
            get { return _ShowOnlyAdditionalServiceRecords; }
            set
            {
                if (_ShowOnlyAdditionalServiceRecords == value)
                    return;

                _ShowOnlyAdditionalServiceRecords = value;
                if (_ShowOnlyAdditionalServiceRecords)
                {
                    FilterServiceRecordsByType(ServiceRecordTypeId.AdditionalService);
                    OnlyWithThisType = ServiceRecordTypeId.AdditionalService;
                }
                else
                {
                    FilterServiceRecordsByType(null);
                    OnlyWithThisType = null;
                }
            }
        }

        public bool ShowOnlyContentServiceRecords
        {
            get { return _ShowOnlyContentServiceRecords; }
            set
            {
                if (_ShowOnlyContentServiceRecords != value)
                {
                    _ShowOnlyContentServiceRecords = value;
                    if (_ShowOnlyContentServiceRecords)
                        FilterServiceRecordsByType(ServiceRecordTypeId.Content);
                    else
                        FilterServiceRecordsByType(null);
                }
            }
        }

        private void FilterServiceRecordsByType(ServiceRecordTypeId? serviceRecordTypeId)
        {
            // Wird nur beim Klick auf Ergänzende Dienste ausgeführt.
            BuildServiceRecordsForTreeNode(_SelectedCustomerNode, false, serviceRecordTypeId);
        }

        public FlatSupportConceptTreeNodeDC SelectedCustomerNode
        {
            get { return _SelectedCustomerNode; }
        }

        public event EventHandler ServiceRecordListChanged;

        public ObservableSortCollection<FlatSupportConceptTreeNodeDC> CustomerNodes
        {
            get
            {
                if (_CustomerNodes == null)
                {
                    _CustomerNodes = new ObservableSortCollection<FlatSupportConceptTreeNodeDC>();
                    _CustomerNodes.CollectionChanged += (s, e) =>
                    {
                        if (e.OldItems != null && e.OldItems.Count > 0)
                        {
                            foreach (FlatSupportConceptTreeNodeDC iNode in e.OldItems)
                            {
                                iNode.IsCustomerWarningActive = false;
                                iNode.CustomerWarning = null;
                            }
                        }

                        FirePropertyChanged(PropertyName_Information);

                        //this.CheckCustomerAbsenceTimes();
                        CheckEmployeeLabourTime();
                    };
                }

                return _CustomerNodes;
            }

            set
            {
                if (AreDifferent(_CustomerNodes, value))
                {
                    _CustomerNodes = value;
                    FirePropertyChanged(PropertyName_CustomerNodes);
                }
            }
        }

        public DispatcherObject DispatcherObject { get; set; }


        public bool IsCustomerWarningActive
        {
            get { return _IsCustomerWarningActive; }

            set
            {
                _IsCustomerWarningActive = value;
                FirePropertyChanged(PropertyName_IsCustomerWarningActive);
            }
        }

        public string CustomerWarning
        {
            get { return _CustomerWarning; }
            set
            {
                _CustomerWarning = value;
                FirePropertyChanged(PropertyName_CustomerWarning);
            }
        }

        public string Information
        {
            get { return string.Empty; }
        }

        public ServiceRecordVM PrototypeVM
        {
            get
            {
                if (_PrototypeVM == null)
                {
                    _PrototypeVM = NewVM;
                    _PrototypeVM.PropertyChanged += (s, e) =>
                    {
                        if (e.PropertyName.Equals(ServiceRecordVM.PropertyName_Duration))
                        {
                            FirePropertyChanged(PropertyName_Information);
                        }

                        CheckCustomerAbsenceTimes();
                        CheckEmployeeLabourTime();
                    };
                }

                return _PrototypeVM;
            }
        }

        public string RecordCountInformationString
        {
            get { return _RecordCountInformationString; }
        }

        public ObservableCollection<DayOfWeek> RecordingDays
        {
            get
            {
                if (_RecordingDays == null)
                {
                    _RecordingDays = new ObservableCollection<DayOfWeek>();
                    //this._RecordingDays.CollectionChanged += (s, e) =>
                    //                                         {
                    //                                             this.CheckCustomerAbsenceTimes();
                    //                                             this.CheckEmployeeLabourTime();
                    //                                         };
                }

                return _RecordingDays;
            }

            set
            {
                if (AreDifferent(_RecordingDays, value))
                {
                    _RecordingDays = value;
                    FirePropertyChanged(PropertyName_RecordingDays);
                }
            }
        }

        public CompactEmployeeDC SelectedEmployee
        {
            get { return mSelectedEmployee; }

            set { mSelectedEmployee = value; }
        }

        //public ServiceRecordVM SelectedVMForEditing { get; set; }

        public BindingList<ServiceRecordVM> ServiceRecordsForSelectedCustomer
        {
            get { return _ServiceRecordsForSelectedCustomer; }
        }

        //public List<SupportConceptTreeNodeDC> Tree { get; private set; }

        public bool WithoutClient { get; set; }

        protected override Comparison<ServiceRecordVM> Comparison
        {
            get { return (x, y) => y.Date.Value.CompareTo(x.Date.Value); }
        }

        DateTime? enddate;

        public List<ServiceRecordVM> CreateFromPrototype()
        {
            var lResult = new List<ServiceRecordVM>();

            
            if (WithoutClient)
            {
                ServiceRecordVM lNewRecord = CreateNewVM();
                lNewRecord.Employee = BeWoApp.LoggedOnUser.Employee;
                lNewRecord.Customer = null;
                lResult.Add(lNewRecord);
            }
            else
            {
                foreach (FlatSupportConceptTreeNodeDC iCustomerNode in _CustomerNodes)
                {
                    ServiceRecordVM lNewRecord = CreateNewVM();

                    enddate = lNewRecord.EndTime;

                    lNewRecord.ChoosenNode = iCustomerNode;
                    lNewRecord.Duration = _PrototypeVM.Duration/_CustomerNodes.Count;

                    if (iCustomerNode.SupportConceptTreeNodeDC != null && lNewRecord.ServiceDescription != null && lNewRecord.ServiceDescription.Category != null &&
                        lNewRecord.ServiceDescription.Category.IsBillable && iCustomerNode.SupportConceptTreeNodeDC.CostBearer != null)
                    {
                        int minuteInterval = iCustomerNode.SupportConceptTreeNodeDC.CostBearer.ActualMinuteIntervall;


                        if (minuteInterval > 0)
                        {
                            Calculations calc = Calculations.GetInstance(iCustomerNode.SupportConceptTreeNodeDC.CostBearer.CostBearerID);
                            decimal lRoudedDuration = calc.GetRoundedDuration(minuteInterval, _PrototypeVM.Duration.Value);

                            lNewRecord.RoundedDuration = lRoudedDuration/_CustomerNodes.Count;
                        }
                    }

                    lNewRecord.EndTime = enddate;
                        
                    lResult.Add(lNewRecord);
                }
            }
            
            // NewVM = null;
            // _PrototypeVM = null;
            FirePropertyChanged(PropertyName_PrototypeVM);

            return lResult;
        }

        public ServiceRecordVM CreateNewVM(ServiceRecordDC pDC)
        {
            ServiceRecordVM lNewRecord = CreateVM(pDC);
            return lNewRecord;
        }

        public Dictionary<DateTimeSpan, decimal?> GetAbsencesTimesWholeWeeks(SupportConceptCostBearerRelDC relDc)
        {
            var lResult = new Dictionary<DateTimeSpan, decimal?>();

            if (_CostBearer2SupportConceptOid2BookingInfoDict.ContainsKey(relDc.CostBearer2SupportConceptOid.Value))
            {
                SupportConceptTreeNodeDetailInfoDC info = _CostBearer2SupportConceptOid2BookingInfoDict[relDc.CostBearer2SupportConceptOid.Value];

                if (info.CustomerAbsenceTimes != null)
                {
                    info.CustomerAbsenceTimes.DoForEach(
                        at => at.AbsenceSpan.GetWholeWeeks().DoForEach(
                            ww =>
                            {
                                if (!lResult.ContainsKey(ww))
                                {
                                    lResult.Add(ww, at.Reason.BillableMinutes);
                                }
                            }));
                }
            }

            return lResult;
        }

        public List<AbsenceTimeDC> GetAbsencesTimeForDate(SupportConceptCostBearerRelDC relDc, DateTime dt)
        {
            if (_CostBearer2SupportConceptOid2BookingInfoDict.ContainsKey(relDc.CostBearer2SupportConceptOid.Value))
            {
                SupportConceptTreeNodeDetailInfoDC info = _CostBearer2SupportConceptOid2BookingInfoDict[relDc.CostBearer2SupportConceptOid.Value];

                if (info.CustomerAbsenceTimes != null)
                {
                    return info.CustomerAbsenceTimes.Where(
                        at => at.AbsenceSpan.ContainsDate(dt)).ToList();
                }
            }

            return null;
        }

        //public List<ValueListEntryDC> GetSupportConceptGoals(SupportConceptCostBearerRelDC relDc)
        //{
        //    List<ValueListEntryDC> list = new List<ValueListEntryDC>();

        //    if (this._CostBearer2SupportConceptOid2BookingInfoDict.ContainsKey(relDc.CostBearer2SupportConceptOid.Value))
        //    {
        //        SupportConceptTreeNodeDetailInfoDC info = this._CostBearer2SupportConceptOid2BookingInfoDict[relDc.CostBearer2SupportConceptOid.Value];

        //        list = info.SupportConceptGoals;
        //    }

        //    return list;
        //}

        public void RefreshServiceRecordsForSelectedTreeNode()
        {
            BuildServiceRecordsForSelectedTreeNode(false);
        }

        internal void ChangeTreeItemSelection(FlatSupportConceptTreeNodeDC lClickedNode)
        {
            if (WithoutClient || _SelectedCustomerNode == null || lClickedNode.SupportConceptTreeNodeDC == null ||
                _SelectedCustomerNode.SupportConceptTreeNodeDC == null ||
                !_SelectedCustomerNode.SupportConceptTreeNodeDC.Customer.EqualsNullCheck(
                    lClickedNode.SupportConceptTreeNodeDC.Customer) ||
                !_SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConcept.EqualsNullCheck(
                    lClickedNode.SupportConceptTreeNodeDC.SupportConcept) ||
                !_SelectedCustomerNode.SupportConceptTreeNodeDC.CostBearer.EqualsNullCheck(
                    lClickedNode.SupportConceptTreeNodeDC.CostBearer))
            {
                _SelectedCustomerNode = lClickedNode;
                CustomerNodes.Clear();

                if (lClickedNode != null)
                {
                    CustomerNodes.Add(lClickedNode);
                }

                BuildServiceRecordsForSelectedTreeNode(false);
            }
        }

        protected override ServiceRecordVM CreateVM(ServiceRecordDC pDC)
        {
            return new ServiceRecordVM(pDC, _Category2Services, null, null);
        }

        private void AddServiceRecordToList(ServiceRecordDC dc, List<ValueListEntryDC> goalCats, List<ValueListEntryDC> goals, FlatSupportConceptTreeNodeDC selectedCustomerNode)
        {
            bool contained = false;

            InitNewDC(dc, selectedCustomerNode);

            // List<ServiceRecordVM> contained = new List<ServiceRecordVM>();
            var groupVMs = new Dictionary<string, ServiceRecordVM>();

            foreach (ServiceRecordVM vm in VMList)
            {
                if (vm.GroupOid != null)
                {
                    string key = String.Format("{0}_{1}", vm.GroupOid.Value, vm.Customer.Oid.Value);
                    if (!groupVMs.ContainsKey(key))
                    {
                        groupVMs.Add(key, vm);
                    }
                }
            }

            foreach (ServiceRecordVM vm in VMList)
            {
                if (vm.DataContract.ServiceRecordOid == dc.ServiceRecordOid)
                {
                    contained = true;
                    break;
                }
                if (dc.GroupOid != null)
                {
                    contained = true;

                    string key = String.Format("{0}_{1}", dc.GroupOid.Value, dc.Customer.Oid.Value);

                    if (groupVMs.ContainsKey(key))
                    {
                        ServiceRecordVM groupVM = groupVMs[key];

                        // groupVM.RoundedDuration = groupVM.GroupRoundedDuration.Value;
                    }
                    else
                    {
                        var newVM = new ServiceRecordVM(dc, _Category2Services, goalCats, goals);

                        // newVM.RoundedDuration = newVM.GroupRoundedDuration.Value;
                        groupVMs.Add(key, newVM);

                        // ###AddServiceRecord
                        VMList.Add(newVM);
                    }

                    break;
                }
            }

            if (!contained)
            {
                // ###AddServiceRecord
                var newVM = new ServiceRecordVM(dc, _Category2Services, goalCats, goals);

                if (dc.GroupOid != null)
                {
                    // newVM.RoundedDuration = newVM.GroupRoundedDuration.Value;
                }

                VMList.Add(newVM);
            }
        }

        private void InitNewDC(ServiceRecordDC newDc, FlatSupportConceptTreeNodeDC selectedCustomerNode)
        {
            if (selectedCustomerNode != null && selectedCustomerNode.SupportConceptTreeNodeDC != null)
            {
                newDc.Customer = selectedCustomerNode.SupportConceptTreeNodeDC.Customer;

                //dc.Customer = new CompactCustomerDC();
                //dc.Customer.CustomerOid = cust.Oid.Value;
                //dc.Customer.CustomerVersion = cust.Version.Value;
                //dc.Customer.FirstName = cust.Person.FirstName;
                //dc.Customer.LastName = cust.Person.LastName;


                newDc.SupportConcept = selectedCustomerNode.SupportConceptTreeNodeDC.SupportConcept;

                if (selectedCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC != null)
                {
                    newDc.CostBearer2SupportConceptOid =
                        selectedCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.
                            CostBearer2SupportConceptOid;

                    newDc.CostBearer =
                        selectedCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer;
                }
                //if (sr.SupportConcept != null)
                //{
                //    dc.SupportConcept = new CompactSupportConceptDC();

                //    dc.SupportConcept.SupportConceptOid = sr.SupportConcept.Oid.Value;
                //    dc.SupportConcept.SupportConceptVersion = sr.SupportConcept.Version.Value;
                //    dc.SupportConcept.Customer = dc.Customer;
                //    dc.SupportConcept.ActivationType = sr.SupportConcept.IsActive;
                //    dc.SupportConcept.ConferenceDate = sr.SupportConcept.ConferenceDate;
                //}

                //Costbearer -----------------
                //if (sr.CostBearer2SupportConcept != null)
                //{
                //    dc.CostBearer2SupportConceptOid = sr.CostBearer2SupportConcept.Oid.Value;

                //    if (dc.SupportConcept != null)
                //    {
                //        CompactCostBearerDC costBearer = new CompactCostBearerDC();

                //        if (sr.CostBearer2SupportConcept.CostBearer.Organisation != null)
                //        {
                //            CompactOrganisationDC orgDC = new CompactOrganisationDC();
                //            orgDC.Name = sr.CostBearer2SupportConcept.CostBearer.Organisation.Name;
                //            orgDC.OrganisationOid = sr.CostBearer2SupportConcept.CostBearer.Organisation.Oid.Value;
                //            orgDC.CostBearerOid = sr.CostBearer2SupportConcept.CostBearer.Oid;
                //            dc.CostBearer = orgDC;
                //            costBearer.Organisation = orgDC;
                //        }
                //        costBearer.CostBearerOid = sr.CostBearer2SupportConcept.CostBearer.Oid.Value;
                //        costBearer.CostBearer2SupportConceptOid = sr.CostBearer2SupportConcept.Oid.Value;
                //        costBearer.SupportConceptStatus = sr.CostBearer2SupportConcept.Status;
                //        costBearer.RequestedStartDate = sr.CostBearer2SupportConcept.RequestedStartDate;
                //        costBearer.RequestedEndDate = sr.CostBearer2SupportConcept.RequestedEndDate;
                //        costBearer.ApprovedStartDate = sr.CostBearer2SupportConcept.ApprovedStartDate;
                //        costBearer.ApprovedEndDate = sr.CostBearer2SupportConcept.ApprovedEndDate;
                //        costBearer.CustomerReferenceNumber = sr.CostBearer2SupportConcept.CustomerReferenceNumber;
                //        costBearer.IsCalculatingWithFactor = sr.CostBearer2SupportConcept.CostBearer.IsCalculatingWithFactor;

                //        dc.SupportConcept.CostBearerList.Add(costBearer);
                //        dc.SupportConcept.CustomerReferenceNumbers.Add(sr.CostBearer2SupportConcept.CustomerReferenceNumber);
                //        dc.SupportConcept.CostBearerRelOids.Add(sr.CostBearer2SupportConcept.Oid.Value);
                //    }

                //    if (dc.CostBearer == null)
                //    {
                //        if (sr.CostBearer2SupportConcept.CostBearer.Organisation != null)
                //            dc.CostBearer = MapperFactory.CompactOrganisationDC_Organisation.MapToNewDC(sr.CostBearer2SupportConcept.CostBearer.Organisation);
                //    }
                //}
            }
        }

        public void BuildServiceRecordsForSelectedTreeNode(bool forceRefreshServiceRecords)
        {
            BuildServiceRecordsForSelectedTreeNode(forceRefreshServiceRecords, null);
        }

        public void BuildServiceRecordsForSelectedTreeNode(bool forceRefreshServiceRecords, Action refreshFinishedCallback)
        {
            long? days = null;
            switch (ServiceRecordTimeInterval)
            {
                case ServiceRecordTimeInterval.LastWeek:
                    days = 7;
                    break;
                case ServiceRecordTimeInterval.LastMonth:
                    days = 30;
                    break;
                case ServiceRecordTimeInterval.Last3Month:
                    days = 90;
                    break;
                case ServiceRecordTimeInterval.LastNDays:
                    days = NDays;
                    break;
            }

            if (WithoutClient)
            {
                CompactEmployeeDC emp = mSelectedEmployee ?? BeWoApp.LoggedOnUser.Employee;

                PrototypeVM.UpdateServiceAccountings(null, _Category2Services, false);

                // TODO: Tage beachten
                //if (!_EmployeeServiceRecordsLoaded.ContainsKey(emp) && DispatcherObject != null)
                if (DispatcherObject != null)
                {
                    ServiceFacade.DoOperationsServiceAsync(s => s.GetEmployeesServiceRecords2(emp.EmployeeOid, days),
                        r => DispatcherObject.Dispatch(delegate
                        {
                            VMList.Clear();
                            foreach (ServiceRecordDC dc in r)
                                AddServiceRecordToList(dc, null, null, null);

                            //_EmployeeServiceRecordsLoaded.Add(emp, true);

                            // BuildServiceRecordsForTreeNode(_SelectedCustomerNode);
                            // if (!_CustomerServiceRecordsLoaded.ContainsKey(customer))
                            // _CustomerServiceRecordsLoaded.Add(customer, true);
                            BuildServiceRecordsForTreeNode(null, true, null);
                        }));
                }
                else
                {
                    BuildServiceRecordsForTreeNode(null, true, null);
                }

                PrototypeVM.ChangeGoalTree(null, null);
            }
            else
            {
                if (_SelectedCustomerNode != null)
                {
                    if (_SelectedCustomerNode.SupportConceptTreeNodeDC == null)
                    {
                        //Gruppen- oder Mehrfachbuchung
                        PrototypeVM.UpdateServiceAccountings(null, _Category2Services, true);

                        BuildServiceRecordsForTreeNode(_SelectedCustomerNode, true, OnlyWithThisType);
                    }
                    else
                    {
                        CompactCustomerDC customer = _SelectedCustomerNode.SupportConceptTreeNodeDC.Customer;

                        if (customer != null)
                        {
                            CompactSupportConceptDC scDC = _SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConcept;

                            SupportConceptTreeNodeDetailInfoDC infoDC;
                            List<ValueListEntryDC> goalCats = null;
                            List<ValueListEntryDC> goals = null;
                            List<ValueListEntryDC> goalsAndCats = null;


                            long cb2scOid = _SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer2SupportConceptOid.Value;

                            if (_CostBearer2SupportConceptOid2BookingInfoDict.ContainsKey(cb2scOid))
                                _CostBearer2SupportConceptOid2BookingInfoDict.Remove(cb2scOid);
                            //if (!_CostBearer2SupportConceptOid2BookingInfoDict.ContainsKey(cb2scOid))
                            //{
                            long? scOidForGoals = null;

                            scOidForGoals = scDC.SupportConceptOid;

                            infoDC = ServiceFacade.DoOperationsServiceSync(s => s.GetSupportConceptTreeNodeDetailInfo(customer.CustomerOid, scOidForGoals, cb2scOid));

                            _CostBearer2SupportConceptOid2BookingInfoDict.Add(cb2scOid, infoDC);
                            //}
                            //else
                            //{
                            //	infoDC = _CostBearer2SupportConceptOid2BookingInfoDict[cb2scOid];
                            //}

                            //if (scDC != null)
                            //{
                            //    var sc = ServiceFacade.DoCustomerServiceSync(s => s.GetSupportConceptsById(new List<long> { scDC.SupportConceptOid })).First();
                            //    goalsAndCats = new List<ValueListEntryDC>(sc.Goals);

                            //    var goalCategoryDict = _AllGoalCategories.ToDictionary(goalCat => goalCat.ValueListEntryOid.Value);

                            //    Parents = new List<ValueListEntryDC>();

                            //    foreach (var child in goalsAndCats)
                            //    {
                            //        if (child.Type.Equals(ValueListEntryType.SupportConceptGoalCategoryType) ||
                            //            child.Type.Equals(ValueListEntryType.SupportConceptGoalType) ||
                            //            child.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalCategoryType))
                            //        {
                            //            GetGoalParents(child, goalCategoryDict);
                            //        }
                            //    }

                            //    goalsAndCats.AddRange(Parents);
                            //}


                            if (infoDC != null && infoDC.SupportConceptGoals != null && infoDC.SupportConceptGoals.Count > 0)
                            {
                                goalCats = new List<ValueListEntryDC>();
                                goals = new List<ValueListEntryDC>();


                                Dictionary<long, ValueListEntryDC> goalCategoryDict = _AllGoalCategories.ToDictionary(goalCat => goalCat.ValueListEntryOid.Value);

                                foreach (ValueListEntryDC goal in infoDC.SupportConceptGoals)
                                {
                                    if (goal.ParentOid != null && goalCategoryDict.ContainsKey(goal.ParentOid.Value))
                                    {
	                                    IEnumerable<ValueListEntryDC> path = GetAllParentGoalCategoies(goalCategoryDict, goal);
	                                    foreach (var goalCat in path)
	                                    {
		                                    goalCats.Add(goalCat);
		                                    goalCategoryDict.Remove(goalCat.ValueListEntryOid.Value);
	                                    }
                                    }

                                    goals.Add(goal);
                                }
                            }
                            if (infoDC != null)
                            {
                                _SelectedCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.ApprovalPeriodList = infoDC.ApprovalPeriods;

                                if (!IsGroupBooking && !IsMultiBooking)
                                    PrototypeVM.UpdateServiceAccountings(infoDC.ServiceAccountings, _Category2Services, true);
                            }

                            String key = String.Format("{0}_{1}", customer.Oid, cb2scOid);


                            //bool refresh = true;

                            //if (!forceRefreshServiceRecords && _ServiceRecordsLoaded.ContainsKey(key))
                            //{
                            //	long maxDaysInCache = _ServiceRecordsLoaded[key];
                            //	if ((days ?? long.MaxValue) <= maxDaysInCache)
                            //		refresh = false;
                            //}

                            //if (!refresh)
                            //	BuildServiceRecordsForTreeNode(_SelectedCustomerNode, true, OnlyWithThisType);
                            //else
                            //{

                            if (DispatcherObject != null)
                            {
                                ServiceFacade.DoOperationsServiceAsync(
                                    s =>
                                        s.GetCustomerServiceRecordsCompact(customer.CustomerOid, cb2scOid, days),
                                    r => DispatcherObject.Dispatch(delegate
                                    {
                                        VMList.Clear();
                                        foreach (ServiceRecordDC dc in r)
                                            AddServiceRecordToList(dc, goalCats, goals, _SelectedCustomerNode);

                                        BuildServiceRecordsForTreeNode(_SelectedCustomerNode, true, OnlyWithThisType);
                                        //_ServiceRecordsLoaded[key] = (days ?? long.MaxValue);

                                        if (refreshFinishedCallback != null)
                                            refreshFinishedCallback();
                                    }));
                            }
                            //}

                            PrototypeVM.ChangeGoalTree(goalCats, goals);
                        }
                    }
                }
            }
        }

		private static IEnumerable<ValueListEntryDC> GetAllParentGoalCategoies(Dictionary<long, ValueListEntryDC> goalCategoryDict, ValueListEntryDC goal)
		{
			IList<ValueListEntryDC> path = new List<ValueListEntryDC>();


			if (goal.ParentOid.HasValue && goalCategoryDict.ContainsKey(goal.ParentOid.Value))
			{
				ValueListEntryDC parentCat = goalCategoryDict[goal.ParentOid.Value];

				while (parentCat != null)
				{
					path.Add(parentCat);
					if (parentCat.ParentOid.HasValue && goalCategoryDict.ContainsKey(parentCat.ParentOid.Value))
					{
						parentCat = goalCategoryDict[parentCat.ParentOid.Value];
					}
					else
					{
						parentCat = null;
					}
				}
			}
			return path;
		}

        private List<ValueListEntryDC> Parents;

        public void GetGoalParents(ValueListEntryDC child, Dictionary<long, ValueListEntryDC> possibleParents)
        {
            while (true)
            {
                if (child.ParentOid != null && possibleParents.ContainsKey(child.ParentOid.Value) && !Parents.Contains(possibleParents[child.ParentOid.Value]))
                {
                    Parents.Add(possibleParents[child.ParentOid.Value]);
                    child = possibleParents[child.ParentOid.Value];
                    continue;
                }
                break;
            }
        }

        private void BuildServiceRecordsForTreeNode(FlatSupportConceptTreeNodeDC treeNode, bool fetchStatistics, ServiceRecordTypeId? onlyWithThisType)
        {
            _ServiceRecordsForSelectedCustomer.Clear();
            _RecordCountInformationString = null;
            if (fetchStatistics)
                Statistics = null;

            if (WithoutClient || (treeNode != null && treeNode.SupportConceptTreeNodeDC != null))
            {
                SupportConceptCostBearerRelDC relDC = null;

                if (!WithoutClient)
                {
                    relDC = treeNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC;
                }

                Func<ServiceRecordVM, bool> f;
                if (WithoutClient)
                {
                    CompactEmployeeDC emp = SelectedEmployee ?? BeWoApp.LoggedOnUser.Employee;

                    f = vm => (vm.Customer == null || vm.SupportConcept == null || vm.CostBearer == null) && emp.Equals(vm.Employee);
                }
                else
                {
                    if (treeNode.SupportConceptTreeNodeDC.CostBearer != null)
                    {
                        f = vm =>
                            treeNode.SupportConceptTreeNodeDC.Customer.Equals(vm.Customer) &&
                            treeNode.SupportConceptTreeNodeDC.SupportConcept.Equals(vm.SupportConcept) &&
                            treeNode.SupportConceptTreeNodeDC.CostBearer.Equals(vm.CostBearer) &&
                            (!onlyWithThisType.HasValue /*&& vm.ServiceRecordType != ServiceRecordTypeId.AdditionalService*/||
                             onlyWithThisType.HasValue && vm.ServiceRecordType == onlyWithThisType.Value);
                    }
                    else if (treeNode.SupportConceptTreeNodeDC.SupportConcept != null)
                    {
                        f = vm =>
                            treeNode.SupportConceptTreeNodeDC.Customer.Equals(vm.Customer) &&
                            treeNode.SupportConceptTreeNodeDC.SupportConcept.Equals(vm.SupportConcept) &&
                            (!onlyWithThisType.HasValue /* && vm.ServiceRecordType != ServiceRecordTypeId.AdditionalService */||
                             onlyWithThisType.HasValue && vm.ServiceRecordType == onlyWithThisType.Value);
                    }
                    else
                    {
                        f = vm =>
                            treeNode.SupportConceptTreeNodeDC.Customer.Equals(vm.Customer) &&
                            (!onlyWithThisType.HasValue /* && vm.ServiceRecordType != ServiceRecordTypeId.AdditionalService */||
                             onlyWithThisType.HasValue && vm.ServiceRecordType == onlyWithThisType.Value);
                    }
                }

                //var recordsUpToDate = ServiceFacade.DoOperationsServiceSync(s => s.GetCustomerServiceRecords(treeNode.SupportConceptTreeNodeDC.Customer.Oid.Value, false));
                //VMList.Clear();
                //foreach (var record in recordsUpToDate.Where(r => 
                //	r.SupportConcept.SupportConceptOid.Equals(treeNode.SupportConceptTreeNodeDC.SupportConcept.SupportConceptOid) && 
                //	r.CostBearer2SupportConceptOid.Value.Equals(treeNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC.CostBearer2SupportConceptOid.Value)))
                //{

                //	if (record.GroupOid.HasValue && VMList.Any(x => x.GroupOid.HasValue && x.GroupOid.Equals(record.GroupOid)))
                //			continue;

                //	VMList.Add(CreateVM(record));
                //}

                foreach (ServiceRecordVM vm in VMList.Where(f))
                {
                    long? days = null;
                    switch (ServiceRecordTimeInterval)
                    {
                        case ServiceRecordTimeInterval.LastWeek:
                            days = 7;
                            break;
                        case ServiceRecordTimeInterval.LastMonth:
                            days = 30;
                            break;
                        case ServiceRecordTimeInterval.Last3Month:
                            days = 90;
                            break;
                        case ServiceRecordTimeInterval.LastNDays:
                            days = NDays;
                            break;
                    }

                    DateTime minDate = DateTime.MinValue;
                    if (days.HasValue)
                    {
                        minDate = DateTime.Now.Date.AddDays(-1*days.Value);
                    }
                    if (vm.StartDate >= minDate)
                        _ServiceRecordsForSelectedCustomer.Add(vm);
                }

                if (!WithoutClient && relDC != null)
                {
                    if (fetchStatistics)
                    {
                        ServiceFacade.DoOperationsServiceAsync(
                            s1 =>
                                s1.GetServiceRecordStatisticInfo(relDC.CostBearer2SupportConceptOid.Value, DateTime.Now),
                            stinf =>
                                ServiceFacade.DoOperationsServiceAsync(
                                    s =>
                                        s.CreateSupportConceptStatistics(relDC.CostBearer2SupportConceptOid.Value, DateTime.Now),
                                    r => DispatcherObject.Dispatch(delegate
                                    {
                                        StatisticsDC = r;
                                        if (stinf != null && StatisticInfosLoaded != null)
                                        {
                                            StatisticInfosLoaded(stinf, new EventArgs());
                                        }
                                        else
                                        {
                                            Statistics = CreateStatisticVMList(r);
                                        }
                                    }), false));
                    }
                }

                _RecordCountInformationString = "Anzahl Einträge: " + _ServiceRecordsForSelectedCustomer.Count;
            }

            FirePropertyChanged(PropertyName_ServiceRecordsForSelectedCustomer);
            FirePropertyChanged(PropertyName_RecordCountInformationString);

            if (ServiceRecordListChanged != null)
            {
                ServiceRecordListChanged(this, new EventArgs());
            }
        }

        private static List<SupportConceptPeriodStatisticsVM> CreateStatisticVMList(SupportConceptStatisticsDC statisticsDc)
        {
            var stats =
                new List<SupportConceptPeriodStatisticsVM>();
            if (statisticsDc != null)
            {
                if (statisticsDc.PeriodStatistics.Count > 1 && !TimeSpanIsEqual(statisticsDc))
                    stats.Add(CreateTotalStatisticsVM(statisticsDc));

                foreach (SupportConceptPeriodStatisticsDC dc in statisticsDc.PeriodStatistics)
                {
                    bool showOutOfPeriod = statisticsDc.PeriodStatistics.Count == 1;
                    stats.Add(CreateStatisticsVM(statisticsDc, dc, showOutOfPeriod));
                }
            }
            return stats;
        }

        public static SupportConceptPeriodStatisticsVM CreateTotalStatisticsVM(SupportConceptStatisticsDC dc)
        {
            int unitDividend = 60;

            var vm = new SupportConceptPeriodStatisticsVM();
            vm.Header = "Gesamt";

            String tenant = BeWoApp.Tenant;

#if DEBUG
            //tenant = "3057313346";
#endif

            if (tenant == "3057313346" || tenant == "2918696314")
            {
                unitDividend = 1;
                vm.StatisticInfo1Left = String.Format("{0:0.00}", dc.MinutesProvidedThisWeek/unitDividend);
                vm.StatisticInfo1Right = String.Format("{0:0.00}", dc.MinutesProvidedTotalRounded/unitDividend);

                vm.StatisticInfo2Left = String.Format("{0:0.00}", dc.MinutesApprovedPerWeek/unitDividend);
                vm.StatisticInfo2Right = String.Format("{0:0.00}", dc.MinutesApprovedTotal/unitDividend);

                vm.StatisticInfo3Left = String.Format("{0:0.00}", dc.MinutesFreePerWeekAverage/unitDividend);
                vm.StatisticInfo3Right = String.Format("{0:0.00}", (dc.MinutesApprovedTotal - dc.MinutesProvidedTotalRounded)/unitDividend);

                vm.StatisticInfo4Left = String.Format("{0:0.00}", dc.MinutesProvidedThisMonth/unitDividend);
                vm.StatisticInfo4Right = String.Format("{0:0.00}", dc.MinutesApprovedPerMonth/unitDividend);

                vm.StatisticInfo5Left = String.Format("{0:0.00}", dc.SollTotalUntilThisMonth/unitDividend);
                vm.StatisticInfo5Right = String.Format("{0:0.00}", dc.IstTotalUntilThisMonth/unitDividend);
            }
            else
            {
                vm.StatisticInfo1Left = String.Format("{0:0.00}", dc.MinutesProvidedThisWeek/unitDividend);
                vm.StatisticInfo1Right = String.Format("{0:0.00}", dc.MinutesProvidedTotalRounded/unitDividend);

                vm.StatisticInfo2Left = String.Format("{0:0.00}", dc.MinutesApprovedPerWeek/unitDividend);
                vm.StatisticInfo2Right = String.Format("{0:0.00}", dc.MinutesApprovedTotal/unitDividend);

                vm.StatisticInfo3Left = String.Format("{0:0.00}", dc.MinutesFreePerWeekAverage/unitDividend);
                vm.StatisticInfo3Right = String.Format("{0:0.00}", (dc.MinutesApprovedTotal - dc.MinutesProvidedTotalRounded)/unitDividend);
            }


            vm.MinutesProvidedTotalRounded = dc.MinutesProvidedTotalRounded;
            return vm;
        }

        public static SupportConceptPeriodStatisticsVM CreateStatisticsVM(SupportConceptStatisticsDC stats, SupportConceptPeriodStatisticsDC periodStats, bool showOutOfPeriod)
        {
            int unitDividend = 60;

            var vm = new SupportConceptPeriodStatisticsVM();
            if (periodStats.SupportConceptApprovalPeriod != null)
            {
                if (periodStats.SupportConceptApprovalPeriod.ServiceCategory != null)
                {
                    if (periodStats.SupportConceptApprovalPeriod.StartDate.HasValue && periodStats.SupportConceptApprovalPeriod.EndDate.HasValue &&
                        periodStats.SupportConceptApprovalPeriod.StartDate.Value.Date == stats.StatisticsStartDate.Date &&
                        periodStats.SupportConceptApprovalPeriod.EndDate.Value.Date == stats.StatisticsEndDate.Date)
                    {
                        vm.Header = periodStats.SupportConceptApprovalPeriod.ServiceCategory.Name;
                    }
                    else
                    {
                        vm.Header = String.Format("{0}: {1:dd.MM.yy} - {2:dd.MM.yy}",
                            periodStats.SupportConceptApprovalPeriod.ServiceCategory.Name,
                            periodStats.SupportConceptApprovalPeriod.StartDate,
                            periodStats.SupportConceptApprovalPeriod.EndDate);
                    }
                }
                else
                {
                    vm.Header = String.Format("{0:dd.MM.yy} - {1:dd.MM.yy}",
                        periodStats.SupportConceptApprovalPeriod.StartDate,
                        periodStats.SupportConceptApprovalPeriod.EndDate);
                }
            }
            String tenant = BeWoApp.Tenant;

#if DEBUG
            //tenant = "3057313346";
#endif
            if (tenant == "3057313346" || tenant == "2918696314")
            {
                unitDividend = 1;
                vm.StatisticInfo1Left = String.Format("{0:0.00}", periodStats.MinutesProvidedTotalRounded/unitDividend);
                vm.StatisticInfo1Right = String.Format("{0:0.00}", periodStats.MinutesApprovedTotal/unitDividend);

                vm.StatisticInfo2Left = String.Format("{0:0.00}", periodStats.MinutesProvidedThisWeek/unitDividend);
                vm.StatisticInfo2Right = String.Format("{0:0.00}", periodStats.MinutesApprovedPerWeek/unitDividend);

                vm.StatisticInfo3Left = String.Format("{0:0.00}", periodStats.MinutesProvidedThisMonth/unitDividend);
                vm.StatisticInfo3Right = String.Format("{0:0.00}", periodStats.MinutesApprovedPerMonth/unitDividend);

                vm.StatisticInfo4Left = String.Format("{0:0.00}",
                    (periodStats.SollTotalUntilThisMonth - periodStats.IstTotalUntilThisMonth)/
                    unitDividend);
            }
            else
            {
                vm.StatisticInfo1Left = String.Format("{0:0.00}", periodStats.MinutesProvidedThisWeek/unitDividend);
                vm.StatisticInfo1Right = String.Format("{0:0.00}", periodStats.MinutesProvidedTotalRounded/unitDividend);

                vm.StatisticInfo2Left = String.Format("{0:0.00}", periodStats.MinutesApprovedPerWeek/unitDividend);
                vm.StatisticInfo2Right = String.Format("{0:0.00}", periodStats.MinutesApprovedTotal/unitDividend);

                vm.StatisticInfo3Left = String.Format("{0:0.00}", periodStats.MinutesFreePerWeek/unitDividend);
                vm.StatisticInfo3Right = String.Format("{0:0.00}",
                    (periodStats.MinutesApprovedTotal - periodStats.MinutesProvidedTotalRounded)/
                    unitDividend);
            }
            if (showOutOfPeriod && stats.MinutesOutOfApprovedPeriod > 0)
                vm.StatisticInfo1Error = String.Format("  {0:0.00}", stats.MinutesOutOfApprovedPeriod/60);

            vm.MinutesProvidedTotalRounded = periodStats.MinutesProvidedTotalRounded;

            return vm;
        }

        private static bool TimeSpanIsEqual(SupportConceptStatisticsDC r)
        {
            if (r.PeriodStatistics != null && r.PeriodStatistics.Count > 1)
            {
                for (int i = 0; i < r.PeriodStatistics.Count - 1; i++)
                {
                    SupportConceptPeriodStatisticsDC p1 = r.PeriodStatistics[i];

                    if (p1.SupportConceptApprovalPeriod.StartDate.HasValue && p1.SupportConceptApprovalPeriod.EndDate.HasValue)
                    {
                        for (int j = i + 1; j < r.PeriodStatistics.Count; j++)
                        {
                            SupportConceptPeriodStatisticsDC p2 = r.PeriodStatistics[j];
                            if (p2.SupportConceptApprovalPeriod.StartDate.HasValue && p2.SupportConceptApprovalPeriod.EndDate.HasValue)
                            {
                                if ((p1.SupportConceptApprovalPeriod.StartDate.Value.Date != p2.SupportConceptApprovalPeriod.StartDate.Value.Date) ||
                                    (p1.SupportConceptApprovalPeriod.EndDate.Value.Date != p2.SupportConceptApprovalPeriod.EndDate.Value.Date))
                                    return false;
                            }
                        }
                    }
                }
            }
            return true;
        }

        private decimal CalculateDurationSum(FlatSupportConceptTreeNodeDC pCustomerNode)
        {
            decimal lResult = 0m;

            if (_PrototypeVM.Duration > 0)
            {
                lResult = Convert.ToDecimal(_PrototypeVM.RoundedDuration)/_CustomerNodes.Count;

                if (_PrototypeVM.ServiceDescription != null && _PrototypeVM.ServiceDescription.Category != null && _PrototypeVM.ServiceDescription.Category.IsBillable &&
                    pCustomerNode.SupportConceptTreeNodeDC.CostBearer != null)
                {
                    int mi = pCustomerNode.SupportConceptTreeNodeDC.CostBearer.ActualMinuteIntervall;

                    if (mi > 0)
                    {
                        lResult = lResult%mi != 0
                            ? lResult + (mi - (lResult%mi))
                            : lResult;
                    }
                }
            }

            return lResult; // *this.GetBookingDates().Count();
        }

        private void CheckCustomerAbsenceTimes()
        {
            IsCustomerWarningActive = false;

            if (!WithoutClient)
            {
                if (CustomerNodes != null)
                {
                    foreach (FlatSupportConceptTreeNodeDC iCustomerNode in CustomerNodes)
                    {
                        if (iCustomerNode.SupportConceptTreeNodeDC != null &&
                            iCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC != null)
                        {
                            List<AbsenceTimeDC> atList =
                                GetAbsencesTimeForDate(
                                    iCustomerNode.SupportConceptTreeNodeDC.SupportConceptCostBearerRelDC,
                                    PrototypeVM.StartDate.Value);
                            if (atList != null && atList.Count > 0)
                            {
                                IsCustomerWarningActive = true;

                                CustomerWarning = "";
                                AbsenceTimeDC atCurrent = null;
                                foreach (AbsenceTimeDC at in atList)
                                {
                                    if (CustomerWarning.Length > 0)
                                        CustomerWarning += "\n";
                                    CustomerWarning += String.Format("{0} von {1:d} bis {2}", at.Reason.Description,
                                        at.Start,
                                        at.End.HasValue
                                            ? String.Format("{0:d}", at.End)
                                            : "unbekannt");

                                    if (at.Reason.BillableMinutes.HasValue && at.Reason.BillableMinutes.Value > 0)
                                        atCurrent = at;
                                }


                                if (atCurrent != null)
                                {
                                    DateTimeSpan week = null;
                                    decimal maxBillableMinutes = atCurrent.Reason.BillableMinutes.Value;

                                    IEnumerable<DateTimeSpan> lAbsenceWeeks = atCurrent.AbsenceSpan.GetWholeWeeks();
                                    foreach (DateTimeSpan lAbsenceWeek in lAbsenceWeeks)
                                    {
                                        if (PrototypeVM.StartDate.Value.InBetween(lAbsenceWeek, true))
                                        {
                                            week = lAbsenceWeek;
                                        }
                                    }


                                    //iCustomerNode.IsCustomerWarningActive = false;
                                    //iCustomerNode.CustomerWarning = null;
                                    DateTime start = atCurrent.Start.Value.Date;
                                    DateTime end = atCurrent.End.HasValue
                                        ? atCurrent.End.Value.Date
                                        : DateTime.MaxValue;

                                    if (week != null)
                                    {
                                        decimal lExisitingFLMInAbsenceWeek =
                                            VMList.Where(
                                                sr =>
                                                    sr.Customer != null &&
                                                    sr.Customer.Equals(iCustomerNode.SupportConceptTreeNodeDC.Customer) &&
                                                    sr.ServiceDescription != null &&
                                                    sr.ServiceDescription.Category.IsBillable &&
                                                    sr.Date.Value.InBetween(week, true) &&
                                                    sr.StartDate.Value.Date != start &&
                                                    sr.StartDate.Value.Date != end)
                                                .Sum(sr => sr.RoundedDuration);

                                        decimal lNewFLMInAbsenceWeek = CalculateDurationSum(iCustomerNode);

                                        //if (lExisitingFLMInAbsenceWeek + lNewFLMInAbsenceWeek > lAbsenceWeek.Value)
                                        //{
                                        //iCustomerNode.IsCustomerWarningActive = true;

                                        CustomerWarning +=
                                            "\nAbrechenbar in dieser Woche: " +
                                            maxBillableMinutes +
                                            " Minuten\n\nBereits geleistet: " +
                                            BeWoWpfUtils.GetDecimalValueWithMaxDecimal(lExisitingFLMInAbsenceWeek, 2);

                                        //" Minuten\nNeue Buchung(en) in der Maske: " + BeWoWpfUtils.GetDecimalValueWithMaxDecimal(lNewFLMInAbsenceWeek, 2) + " Minuten" +

                                        decimal notBillableMinutes =
                                            BeWoWpfUtils.GetDecimalValueWithMaxDecimal(
                                                -(maxBillableMinutes -
                                                  (lExisitingFLMInAbsenceWeek + lNewFLMInAbsenceWeek)), 2) ?? 0;
                                        if (notBillableMinutes > 0)
                                        {
                                            CustomerWarning += "\nEs werden " + notBillableMinutes +
                                                               " Minuten verfallen";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private static void CheckEmployeeLabourTime()
        {
        }

        private ServiceRecordVM CreateNewVM()
        {
            ServiceRecordVM lNewRecord = _PrototypeVM.Clone();

			//if (lNewRecord.EndTime == null || (lNewRecord.StartDate.Value.Date == lNewRecord.EndTime.Value.Date))
            //{
				//lNewRecord.Date = _PrototypeVM.Dat.Value.GetInSameCalendarWeek(pDay);
				//lNewRecord.Duration = _PrototypeVM.Duration;
            //}

			lNewRecord.Date = _PrototypeVM.Date;
			lNewRecord.Duration = _PrototypeVM.Duration;

            if (_PrototypeVM.Duration.HasValue)
                lNewRecord.RoundedDuration = _PrototypeVM.Duration.Value;

            lNewRecord.SetInsertedOn(DateTime.Now);
            lNewRecord.InsUser = BeWoApp.LoggedOnUser.Employee.FirstName + " " + BeWoApp.LoggedOnUser.Employee.LastName;

            //lNewRecord.ServiceRecordType = this._PrototypeVM.ServiceRecordType;

            return lNewRecord;
        }

        //private List<DateTime> GetBookingDates()
        //{
        //    if (this._PrototypeVM != null && this._PrototypeVM.Date != null && this._RecordingDays != null)
        //    {
        //        return this._RecordingDays.Select(d => this._PrototypeVM.Date.Value.GetInSameCalendarWeek(d)).ToList();
        //    }

        //    return new List<DateTime>();
        //}

        public bool IsGroupBooking { get; set; }

        public bool IsMultiBooking { get; set; }

        internal decimal GetFLSTotal(ServiceRecordVM vm)
        {
            if (Statistics != null && Statistics.Count > 0)
            {
                return Statistics[0].MinutesProvidedTotalRounded/60;
            }
            return 0;
        }

        public SupportConceptStatisticsDC StatisticsDC { get; set; }

        internal static GroupDurationDC CalculateGroupDuration(int personCount, int employeeCount, decimal totalDuration, List<long> costBearer2SupportConceptList)
        {
            return ServiceFacade.DoOperationsServiceSync(s => s.CalculateGroupDuration2(personCount, employeeCount, totalDuration, costBearer2SupportConceptList));
            return null;
        }
    }
}