using System.Collections.Generic;
using System.Linq;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.ClientPartials;
using BS.Shared.DataContracts.Compact;

namespace BeWo.Core.Service
{
    public class SupportConceptService
    {
        public static List<SupportConceptGoalDC> CreateGoalTree_ALT(List<ValueListEntryDC> allGoalCategories, List<ValueListEntryDC> allGoals, ObservableSortCollection<ValueListEntryDC> selectedGoals)
        {
            var goalList = new List<SupportConceptGoalDC>();

            if (allGoalCategories != null && allGoals != null)
            {
                List<ValueListEntryDC> sortedCategories = allGoalCategories.OrderBy(s => s.TypeDescription).ToList();
                List<ValueListEntryDC> sortedGoals = allGoals.OrderBy(s => s.TypeDescription).ToList();

                var goalCategoryDict = new Dictionary<long, SupportConceptGoalDC>();

                foreach (ValueListEntryDC goalCat in sortedCategories)
                {
                    var treeItem = new SupportConceptGoalDC {GoalEntryDC = goalCat, IsExpanded = true};
                    goalCategoryDict.Add(goalCat.ValueListEntryOid.Value, treeItem);
                    goalList.Add(treeItem);
                }

                foreach (ValueListEntryDC goal in sortedGoals)
                {
                    var childItem = new SupportConceptGoalDC {GoalEntryDC = goal};

                    if (goal.ParentOid != null && goalCategoryDict.ContainsKey(goal.ParentOid.Value))
                    {
                        SupportConceptGoalDC parentItem = goalCategoryDict[goal.ParentOid.Value];
                        childItem.ParentGoal = parentItem;

                        if (selectedGoals != null)
                        {
                            foreach (ValueListEntryDC existingGoal in selectedGoals)
                            {
                                if (existingGoal.Equals(goal))
                                {
                                    childItem.IsChecked = true;
                                }
                            }

                            childItem.PropertyChanged += (s, e) =>
                            {
                                var selectedGoal = s as SupportConceptGoalDC;
                                if (selectedGoal != null)
                                {
                                    if (selectedGoal.IsChecked)
                                    {
                                        selectedGoals.Add(selectedGoal.GoalEntryDC);
                                    }
                                    else
                                    {
                                        selectedGoals.Remove(selectedGoal.GoalEntryDC);
                                    }
                                }
                            };
                        }


                        parentItem.Children.Add(childItem);
                    }
                }
            }

            return goalList;
        }

        public static List<SupportConceptGoalDC> CreateGoalTree(List<ValueListEntryDC> allGoalsAndCategories, ObservableSortCollection<ValueListEntryDC> selectedGoals)
        {
            var goalList = new List<SupportConceptGoalDC>();

            if (allGoalsAndCategories != null)
            {
                var ziele            = allGoalsAndCategories.Where(w => w.Type.Equals(ValueListEntryType.SupportConceptGoalCategoryType) || w.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalCategoryType)).OrderBy(s => s.TypeDescription).ToList();
                var massnahmen       = allGoalsAndCategories.Where(w => w.Type.Equals(ValueListEntryType.SupportConceptGoalType) || w.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalType)).OrderBy(s => s.TypeDescription).ToList();
                var goalCategoryDict = new Dictionary<long, SupportConceptGoalDC>();
                

                foreach (var goalCat in ziele)
                {
                    var treeItem = new SupportConceptGoalDC
                    {
                        GoalEntryDC = goalCat, 
                        IsExpanded  = true
                    };
	                if (!goalCategoryDict.ContainsKey(goalCat.ValueListEntryOid.Value))
	                {
		                goalCategoryDict.Add(goalCat.ValueListEntryOid.Value, treeItem);
	                }

	                if(goalCat.ParentOid == null)
                    {
                        goalList.Add(treeItem);
                    }
                }

                foreach (var ziel in ziele.Where(w => w.ParentOid != null))
                {
					if (goalCategoryDict.ContainsKey(ziel.ParentOid.Value) && goalCategoryDict.ContainsKey(ziel.ValueListEntryOid.Value))
	                {
		                goalCategoryDict[ziel.ValueListEntryOid.Value].ParentGoal = goalCategoryDict[ziel.ParentOid.Value];
	                }
                }

                var zieleMitEltern = goalCategoryDict.Values.Where(w => w.GoalEntryDC.ParentOid != null).ToList();
                foreach (var ziel in zieleMitEltern)
                {
					if (goalCategoryDict.ContainsKey(ziel.GoalEntryDC.ParentOid.Value))
	                {
		                goalCategoryDict[ziel.GoalEntryDC.ParentOid.Value].Children.Add(ziel);
	                }
                }

				var zieleOhneKinder = goalCategoryDict.Values.Where(w => w.Children.Count == 0).ToList();
				foreach (var ziel in zieleOhneKinder)
				{
					CheckIfSelected(ziel, selectedGoals);
				}

                foreach (var goal in massnahmen)
                {
                    var kind = new SupportConceptGoalDC { GoalEntryDC = goal };

	                CheckIfSelected(kind, selectedGoals);

                    if (goal.ParentOid != null && goalCategoryDict.ContainsKey(goal.ParentOid.Value))
                    {
                        var parentItem = goalCategoryDict[goal.ParentOid.Value];
                        kind.ParentGoal = parentItem;

                        parentItem.Children.Add(kind);
                    }
                }
            }

            return goalList;
        }

		private static void CheckIfSelected(SupportConceptGoalDC goal, ObservableSortCollection<ValueListEntryDC> selectedGoals)
		{
			if (selectedGoals != null)
			{
				foreach (ValueListEntryDC existingGoal in selectedGoals)
				{
					if (existingGoal.Equals(goal.GoalEntryDC))
					{
						goal.IsChecked = true;
					}
				}

				goal.PropertyChanged += (s, e) =>
				{
					var selectedGoal = s as SupportConceptGoalDC;
					if (selectedGoal != null)
					{
						if (selectedGoal.IsChecked)
						{
							selectedGoals.Add(selectedGoal.GoalEntryDC);
						}
						else
						{
							selectedGoals.Remove(selectedGoal.GoalEntryDC);
						}
					}
				};
			}
		}

        public static List<ServiceCategoryTreeItem> CreateServiceTree(IList<ServiceCategoryDC> serviceCategories, IList<ServiceDescriptionDC> serviceDescriptions, IList<ServiceAccountingDC> serviceAccountings)
        {
            List<ServiceCategoryTreeItem> treeList = new List<ServiceCategoryTreeItem>();

            if (serviceCategories != null && serviceDescriptions != null)
            {
                List<ServiceCategoryDC> sortedCategories = serviceCategories.Where(sd => !sd.OhneHilfeplan.HasValue ||sd.OhneHilfeplan.Value == AccountingvisibilityType.Beides || sd.OhneHilfeplan.Value == AccountingvisibilityType.NurKlientenbezogen).OrderBy(s => s.Name).ToList();
                List<ServiceAccountingDC> serviceAccountingsCopy = new List<ServiceAccountingDC>();
                List<ServiceDescriptionDC> descriptions = serviceDescriptions.OrderBy(s => s.Name).ToList();

                if (serviceAccountings != null)
                {
                    foreach (var serviceAccountingDc in serviceAccountings)
                    {
                        descriptions.Remove(serviceAccountingDc.ServiceDescription);
                        serviceAccountingsCopy.Add(serviceAccountingDc);
                    }
                }

                foreach (var serviceDescriptionDc in descriptions)
                {
                    ServiceAccountingDC accountingDc = new ServiceAccountingDC();
                    accountingDc.ServiceDescription = serviceDescriptionDc;

                    serviceAccountingsCopy.Add(accountingDc);
                }
                List<ServiceAccountingDC> sortedAccountings = serviceAccountingsCopy.OrderBy(acc => acc.ServiceDescription.Name).ToList();

                Dictionary<long, ServiceCategoryTreeItem> categoryDict = new Dictionary<long, ServiceCategoryTreeItem>();

                foreach (ServiceCategoryDC category in sortedCategories)
                {
                    ServiceCategoryTreeItem treeItem = new ServiceCategoryTreeItem();
                    treeItem.ServiceCategory = category;
                    treeItem.IsExpanded = true;
                    categoryDict.Add(category.ServiceCategoryOid.Value, treeItem);
                    treeList.Add(treeItem);
                }

                foreach (ServiceAccountingDC sa in sortedAccountings)
                {
                    ServiceCategoryTreeItem childItem = new ServiceCategoryTreeItem();
                    childItem.ServiceAccounting = sa;

                    if (sa.ServiceDescription.Category != null && categoryDict.ContainsKey(sa.ServiceDescription.Category.ServiceCategoryOid.Value))
                    {
                        ServiceCategoryTreeItem parentItem = categoryDict[sa.ServiceDescription.Category.ServiceCategoryOid.Value];
                        childItem.Parent = parentItem;

                        //if (selectedDescriptions != null)
                        //{
                        //    foreach (var existingSd in selectedDescriptions)
                        //    {
                        //        if (existingSd.Equals(sd))
                        //        {
                        //            childItem.IsChecked = true;
                        //        }
                        //    }

                        //    childItem.PropertyChanged += (s, e) =>
                        //    {
                        //        ServiceCategoryTreeItem selectedSd = s as ServiceCategoryTreeItem;
                        //        if (selectedSd != null && selectedSd.ServiceDescription != null)
                        //        {
                        //            if (selectedSd.IsChecked)
                        //            {
                        //                selectedDescriptions.Add(selectedSd.ServiceDescription);
                        //            }
                        //            else
                        //            {
                        //                selectedDescriptions.Remove(selectedSd.ServiceDescription);
                        //            }
                        //        }
                        //    };
                        //}

                        parentItem.Children.Add(childItem);
                    }
                }
            }

            return treeList;
        }

        public static FlatSupportConceptTreeNodeDC CreateFlatSupportConceptItem(CompactSupportConceptDC dc, CompactOrganisationDC orga)
        {
            FlatSupportConceptTreeNodeDC flatNode = new FlatSupportConceptTreeNodeDC();
           
            if (dc != null)
            {
                SupportConceptTreeNodeDC treeNode = new SupportConceptTreeNodeDC();
                treeNode.SupportConcept = dc;
                treeNode.Customer = dc.Customer;

                if (dc.CostBearerList.Count > 0)
                {
                    CompactCostBearerDC cbDC = null;

                    if (orga != null) 
                    {
                        foreach (var item in dc.CostBearerList)
                        {
                            if (orga.Equals(item.Organisation))
                            {
                                cbDC = item;
                            }
                        }
                    }
                    if (cbDC == null)
                        cbDC = dc.CostBearerList[0];


                    CompactOrganisationDC orgDC = new CompactOrganisationDC();
                    SupportConceptCostBearerRelDC relDC = new SupportConceptCostBearerRelDC();

                    orgDC.CostBearerID = cbDC.CostBearerID;
                    orgDC.CostBearerOid = cbDC.CostBearerOid;

	                var o = orga;
	                if (o == null && cbDC != null)
		                o = cbDC.Organisation;

					if (o != null)
                    {
						orgDC.OrganisationOid = o.OrganisationOid;
						orgDC.Name = o.Name;
						orgDC.ActualHourlyRate = o.ActualHourlyRate;
						orgDC.ActualMinuteIntervall = o.ActualMinuteIntervall;
						orgDC.ActualRateFactor = o.ActualRateFactor;
						orgDC.CostRatePeriods = o.CostRatePeriods;
						orgDC.IsCalculatingWithFactor = o.IsCalculatingWithFactor;

                    }
					relDC.ApprovedEndDate = cbDC.ApprovedEndDate;
                    relDC.ApprovedStartDate = cbDC.ApprovedStartDate;
                    relDC.CostBearer = orgDC;
                    relDC.CostBearer2SupportConceptOid = cbDC.CostBearer2SupportConceptOid;
                    relDC.RequestedEndDate = cbDC.RequestedEndDate;
                    relDC.RequestedStartDate = cbDC.RequestedStartDate;
                    relDC.Status = cbDC.SupportConceptStatus;
                    relDC.SupportConcept = dc;

                    treeNode.SupportConceptCostBearerRelDC = relDC;
                    treeNode.CostBearer = orgDC;
                }

                flatNode.SupportConceptTreeNodeDC = treeNode;
            }

            return flatNode;
        }
        
    }
}