using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms.VisualStyles;
using BeWo.Core;
using BeWo.Core.Service;
using BeWo.ServiceProxy;
using BeWo.Validation;
using BeWo.ViewModel.ListViewModel;

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.ClientPartials;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using Microsoft.Office.Interop.Word;

namespace BeWo.ViewModel
{
    public class SupportConceptVM : AbstractDCMapperVM<SupportConceptDC>
    {
        public static string PropertyName_ApprovalDate             = "ApprovalDate";
        public static string PropertyName_Conference               = "Conference";
		public static string PropertyName_IsConferenceYes          = "IsConferenceYes";
		public static string PropertyName_IsConferenceNo           = "IsConferenceNo";
		public static string PropertyName_IsConferenceOpen         = "IsConferenceOpen";
        public static string PropertyName_CombinedGoals            = "CombinedGoals";
        public static string PropertyName_ConferenceDate           = "ConferenceDate";
        public static string PropertyName_ConferenceVenue          = "ConferenceVenue";
        public static string PropertyName_ConsultingNeeded         = "ConsultingNeeded";
        public static string PropertyName_CostBearerRelations      = "CostBearerRelations";
        public static string PropertyName_Customer                 = "Customer";
        public static string PropertyName_CustomerString           = "CustomerString";
        public static string PropertyName_Goals                    = "Goals";
        public static string PropertyName_IsArchived               = "IsArchived";
        public static string PropertyName_Notice                   = "Notice";
        public static string PropertyName_Originator               = "Originator";
        public static string PropertyName_RenewalSendDate          = "RenewalSendDate";
        public static string PropertyName_RequisitionSendDate      = "RequisitionSendDate";
        public static string PropertyName_SupportConceptSendDate   = "SupportConceptSendDate";
        public static string PropertyName_Tasks                    = "Tasks";
        public static string PropertyName_GlobalServiceAccountings = "GlobalServiceAccountings";
        

        private DateTime? _ApprovalDate;
        private bool? _Conference;
        private DateTime? _ConferenceDate;
        private string _ConferenceVenue;
        private bool _ConsultingNeeded;
        private SupportConceptCostBearerRelListVM _CostBearerRelations;
        private CompactCustomerDC _Customer;
        private bool _IsArchived;
        private string _Notice;
        private CompactEmployeeDC _Originator;
        private DateTime? _RenewalSendDate;
        private DateTime? _RequisitionSendDate;
        private DateTime? _SupportConceptSendDate;
        private TaskListVM _Tasks;
        private ObservableSortCollection<ServiceAccountingDC> _SelectedGlobalServices;
        private ServiceAccountingListVM _IndividualServices;

        private ObservableSortCollection<ValueListEntryDC> _Goals;
        private GenericValueListEntryListVM                _CombinedGoals;

        private GenericValueListEntryListVM                _IndividualGoals;

        private List<ValueListEntryDC>                     Children2Delete;
        private List<ValueListEntryDC>                     selectedGoals;

        public SupportConceptVM(
            SupportConceptDC pDataContract, 
            List<ValueListEntryDC> pAllGoalCategories, 
            List<ValueListEntryDC> pAllGoals, 
            Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> serviceCategoryDict)

            : base(pDataContract, pDataContract.SupportConceptOid == null)
        {
            //InitGoalCategories(pAllGoalCategories, pAllGoals);
            checkedStateChangedGoals = new List<ValueListEntryVM>();
            InitServiceTrees(serviceCategoryDict);
            InitCombinedGoalTree();
        }

        private void InitCombinedGoalTree()
        {
            var ziele = _IndividualGoals.VMList.Select(s => s.DataContract).ToList();
            ziele.AddRange(ServiceFacade.DoValueListServiceSync(s => s.GetAllValueListEntrysByTypes(new List<ValueListEntryType> { ValueListEntryType.SupportConceptGoalCategoryType, ValueListEntryType.SupportConceptGoalType })));
            
            _CombinedGoals = new GenericValueListEntryListVM(ziele);
            
            var categoriesWithParent = new List<SupportConceptGoalTreeItem>();
            var goalList             = GoalService.GetZieleMassnahmenTree(_CombinedGoals.VMList.ToList(), false);
            var iGoalList            = new ObservableSortCollection<SupportConceptGoalTreeItem>();
            var dictOid2TreeItem     = new Dictionary<long, SupportConceptGoalTreeItem>();

            foreach (var category in goalList)
            {
                var item = new SupportConceptGoalTreeItem
                {
                    GoalEntryDC = category.GoalEntryDC,
                    GoalEntryVM = _CombinedGoals.VMList.FirstOrDefault(f => f.DataContract.ValueListEntryOid.Value == category.GoalEntryDC.ValueListEntryOid.Value),
                    IsExpanded = true,
                    ParentGoal = category.ParentGoal,
					IsChecked = _Goals != null && _Goals.Contains(category.GoalEntryDC)
                };

				item.PropertyChanged += MassnahmeCheckStatusChanged;

                if (item.GoalEntryDC.ParentOid == null)
                {
                    iGoalList.Add(item);
                }
                else
                {
                    categoriesWithParent.Add(item);
                }

                dictOid2TreeItem.Add(category.GoalEntryDC.ValueListEntryOid.Value, item);
            }

            foreach (var category in categoriesWithParent)
            {
                if (category.GoalEntryDC.ParentOid == null || category.GoalEntryDC.ValueListEntryOid == null)
                    continue;

	            if (dictOid2TreeItem.ContainsKey(category.GoalEntryDC.ParentOid.Value))
	            {
		            var parent = dictOid2TreeItem[category.GoalEntryDC.ParentOid.Value];

		            parent.Items.Add(dictOid2TreeItem[category.GoalEntryDC.ValueListEntryOid.Value]);
		            category.ParentGoal = parent;
	            }
            }

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

            foreach (var goal in _CombinedGoals.VMList.Where(w => w.Type.Equals(ValueListEntryType.SupportConceptGoalType) || w.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalType)))
            {
                var item = new SupportConceptGoalTreeItem
                {
                    GoalEntryVM = goal,
                    GoalEntryDC = goal.DataContract,
					IsChecked = _Goals != null && _Goals.Contains(goal.DataContract)
                };

                item.PropertyChanged += MassnahmeCheckStatusChanged;

                if (goal.ParentEntry == null || !dictOid2TreeItem.ContainsKey(goal.ParentEntry.ValueListEntryOid.Value))
                {
                    iGoalList.Add(item);
                }
                else
                {
                    var parent = dictOid2TreeItem[goal.ParentEntry.ValueListEntryOid.Value];
                    parent.Items.Add(item);

                    if (!parent.Children.Contains(item))
                    {
                        parent.Children.Add(item);
                    }

                    item.ParentGoal = parent;
                }
            }

            _CombinedGoalTree = iGoalList;
        }

        private readonly List<ValueListEntryVM> checkedStateChangedGoals;

        private void MassnahmeCheckStatusChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("IsChecked"))
            {
                var item = (SupportConceptGoalTreeItem) sender;

                if (item.IsChecked != _Goals.Contains(item.GoalEntryVM.DataContract))
                {
                    checkedStateChangedGoals.Add(item.GoalEntryVM);
                }
                else if(checkedStateChangedGoals.Contains(item.GoalEntryVM))
                {
                    checkedStateChangedGoals.Remove(item.GoalEntryVM);
                }
            }
        }

        // Veraltet
        //private void InitGoalCategories(List<ValueListEntryDC> pAllGoalCategories, List<ValueListEntryDC> pAllGoals)
        //{
        //    var goalList         = GoalService.GetGoalTree(pAllGoalCategories, pAllGoals, false);
        //    var iGoalList        = new BindingList<SupportConceptGoalTreeItem>();
        //    var dictOid2TreeItem = new Dictionary<long, SupportConceptGoalTreeItem>();
        //    foreach (var goalCat in goalList)
        //    {
        //        foreach (var goal in goalCat.Children)
        //        {
        //            if (_Goals != null)
        //            {
        //                foreach (var existingGoal in _Goals)
        //                {
        //                    if (existingGoal.Equals(goal.GoalEntryDC))
        //                    {
        //                        goal.IsChecked = true;
        //                    }
        //                }
        //            }

        //            goal.PropertyChanged += ChildItem_PropertyChanged;
        //        }
        //        var item = new SupportConceptGoalTreeItem {GoalEntryDC = goalCat.GoalEntryDC, IsExpanded = true};
        //        iGoalList.Add(item);

        //        dictOid2TreeItem.Add(goalCat.GoalEntryDC.ValueListEntryOid.Value, item);
        //    }

        //    //GoalCategories = goalList;

        //    //Create GoalTree
        //    foreach (var goal in _IndividualGoals.VMList)
        //    {
        //        var item = new SupportConceptGoalTreeItem {GoalEntryVM = goal};

        //        if (goal.ParentEntry == null || !dictOid2TreeItem.ContainsKey(goal.ParentEntry.ValueListEntryOid.Value))
        //            iGoalList.Add(item);
        //        else
        //        {
        //            var parent = dictOid2TreeItem[goal.ParentEntry.ValueListEntryOid.Value];
        //            parent.Items.Add(item);
        //            item.ParentGoal = parent;
        //        }
                
        //    }

        //    IndividualGoalTree = iGoalList;
        //}

        private void InitServiceTrees(Dictionary<ServiceCategoryDC, List<ServiceDescriptionDC>> serviceCategoryDict)
        {
            var categories = new List<ServiceCategoryDC>();
            var descriptions = new List<ServiceDescriptionDC>();

            foreach (var cat in serviceCategoryDict.Keys)
            {
                if (cat.ScopeType == ScopeTypeId.Global)
                {
                    categories.Add(cat);
                    descriptions.AddRange(serviceCategoryDict[cat]);
                }
            }

            var serviceList = SupportConceptService.CreateServiceTree(categories, descriptions, _SelectedGlobalServices);

            foreach (var cat in serviceList)
            {
                foreach (var sd in cat.Children)
                {
                    if (this._SelectedGlobalServices != null && _SelectedGlobalServices.Count > 0)
                    {
                        foreach (var existingSd in this._SelectedGlobalServices)
                        {
                            if (existingSd.ServiceDescription.Equals(sd.ServiceAccounting.ServiceDescription))
                            {
                                sd.IsChecked = true;
                                cat.SetChecked(true);
                            }
                        }
                    } 
                    else
                    {
                        sd.IsChecked = true;
                        if (!cat.IsChecked)
                            cat.IsChecked = true;
                    }

                    sd.PropertyChanged += this.GlobalServiceTreeItem_PropertyChanged;
                }
            }

            this.GlobalServiceTree = serviceList;


            //Create IndividualTree
            BindingList<ServiceCategoryTreeItem> iserviceList = new BindingList<ServiceCategoryTreeItem>();
            foreach (var svm in _IndividualServices.VMList)
            {
                ServiceCategoryTreeItem item = new ServiceCategoryTreeItem();
                item.ServiceAccountingVM = svm;
                iserviceList.Add(item);
            }
            this.IndividualServiceTree = iserviceList;
        }

        public DateTime? ApprovalDate
        {
            get { return this._ApprovalDate; }

            set
            {
                if (this.AreDifferent(this._ApprovalDate, value))
                {
                    this._ApprovalDate = value;

                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ApprovalDate, value), PropertyName_ApprovalDate);

                    this.FirePropertyChanged(PropertyName_ApprovalDate);
                }
            }
        }

        public bool? Conference
        {
            get { return this._Conference; }

            set
            {
                if (this.AreDifferent(this._Conference, value))
                {
                    this._Conference = value;
                    this.StoreDirtyInformation(value == this.DataContract.Conference, PropertyName_Conference);
                    this.FirePropertyChanged(PropertyName_Conference);
                }
            }
        }

		public bool IsConferenceYes
		{
			get { return _Conference.HasValue && _Conference.Value; }

			set
			{
				if (value && (!_Conference.HasValue || !_Conference.Value))
				{
					_Conference = true;

					StoreDirtyInformation(true, "Conference");

					FirePropertyChanged(PropertyName_IsConferenceYes);
					FirePropertyChanged(PropertyName_IsConferenceNo);
					FirePropertyChanged(PropertyName_IsConferenceOpen);
				}
			}
		}

		public bool IsConferenceNo
		{
			get { return _Conference.HasValue && !_Conference.Value; }

			set
			{
				if (value && (!_Conference.HasValue || _Conference.Value))
				{
					_Conference = false;

					StoreDirtyInformation(true, "Conference");

					FirePropertyChanged(PropertyName_IsConferenceYes);
					FirePropertyChanged(PropertyName_IsConferenceNo);
					FirePropertyChanged(PropertyName_IsConferenceOpen);
				}
			}
		}

		public bool IsConferenceOpen
		{
			get { return !_Conference.HasValue; }

			set
			{
				if (_Conference.HasValue && value)
				{
					_Conference = null;

					StoreDirtyInformation(true, "Conference");

					FirePropertyChanged(PropertyName_IsConferenceYes);
					FirePropertyChanged(PropertyName_IsConferenceNo);
					FirePropertyChanged(PropertyName_IsConferenceOpen);
				}
			}
		}

        public DateTime? ConferenceDate
        {
            get { return this._ConferenceDate; }

            set
            {
                if (this.AreDifferent(this._ConferenceDate, value))
                {
                    this._ConferenceDate = value;

                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ConferenceDate, value), PropertyName_ConferenceDate);

                    this.FirePropertyChanged(PropertyName_ConferenceDate);
                }
            }
        }

        public string ConferenceVenue
        {
            get { return this._ConferenceVenue; }

            set
            {
                if (this.AreDifferent(this._ConferenceVenue, value))
                {
                    this._ConferenceVenue = value;
                    this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ConferenceVenue, value), PropertyName_ConferenceVenue);
                    this.FirePropertyChanged(PropertyName_ConferenceVenue);
                }
            }
        }

        public bool ConsultingNeeded
        {
            get { return _ConsultingNeeded; }

            set
            {
                if (AreDifferent(_ConsultingNeeded, value))
                {
                    _ConsultingNeeded = value;

                    StoreDirtyInformation(AreDifferent(DataContract.ConsultingNeeded, value), PropertyName_ConsultingNeeded);

                    FirePropertyChanged(PropertyName_ConsultingNeeded);
                }
            }
        }

        public SupportConceptCostBearerRelListVM CostBearerRelations
        {
            get { return _CostBearerRelations; }
        }

        public CompactCustomerDC Customer
        {
            get { return _Customer; }

            set
            {
                if (AreDifferent(_Customer, value))
                {
                    _Customer = value;
                    StoreDirtyInformation(!AreEqual(value, DataContract.Customer), PropertyName_Customer);
                    FirePropertyChanged(PropertyName_Customer);
                    FirePropertyChanged(PropertyName_CustomerString);
                }
            }
        }

        [Validation(ValidationRule = ValidationRules.NotNullOrStringEmpty)]
        public string CustomerString
        {
            get { return _Customer.ToStringNullCheck(); } // Validation Workaround
            set { }
        }

        public List<SupportConceptGoalDC> GoalCategories { get; private set; }

        public BindingList<SupportConceptGoalTreeItem> IndividualGoalTree { get; private set; }

        private ObservableCollection<SupportConceptGoalTreeItem> _CombinedGoalTree;

        public ObservableCollection<SupportConceptGoalTreeItem> CombinedGoalTree
        {
            get
            {
                return _CombinedGoalTree ?? (_CombinedGoalTree = new ObservableCollection<SupportConceptGoalTreeItem>());
            }
        }

        public List<ServiceCategoryTreeItem> GlobalServiceTree { get; private set; }

        public BindingList<ServiceCategoryTreeItem> IndividualServiceTree { get; private set; }


        public ObservableSortCollection<ValueListEntryDC> Goals
        {
            get { return _Goals ?? (_Goals = new ObservableSortCollection<ValueListEntryDC>(Comparer.ValueListEntryDCComparer)); }
        }

        public ObservableSortCollection<ServiceAccountingDC> SelectedGlobalServices
        {
            get { return _SelectedGlobalServices ?? (_SelectedGlobalServices = new ObservableSortCollection<ServiceAccountingDC>(Comparer.ServiceAccountingDCComparer)); }
        }

        public bool IsArchived
        {
            get { return _IsArchived; }

            set
            {
                if (AreDifferent(_IsArchived, value))
                {
                    _IsArchived = value;
                    StoreDirtyInformation(
                        (value && DataContract.ActivationType == ActivationTypeId.Active) || (!value && DataContract.ActivationType == ActivationTypeId.Archived), PropertyName_IsArchived);
                    FirePropertyChanged(PropertyName_IsArchived);
                }
            }
        }

        public override bool IsDirty
        {
            get
            {
                if (CostBearerRelations == null || Tasks == null)
                {
                    return false;
                }

                return base.IsDirty || CostBearerRelations.IsDirty || Tasks.IsDirty ||
                       _IndividualServices.IsDirty || _CombinedGoals.IsDirty || checkedStateChangedGoals.Count > 0;
            }
        }

        public string Notice
        {
            get { return _Notice; }

            set
            {
                if (AreDifferent(_Notice, value))
                {
                    _Notice = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Notice, value), PropertyName_Notice);
                    FirePropertyChanged(PropertyName_Notice);
                }
            }
        }

        public CompactEmployeeDC Originator
        {
            get { return _Originator; }

            set
            {
                if (AreDifferent(_Originator, value))
                {
                    _Originator = value;
                    StoreDirtyInformation(!AreEqual(value, DataContract.Originator), PropertyName_Originator);
                    FirePropertyChanged(PropertyName_Originator);
                }
            }
        }

        public DateTime? RenewalSendDate
        {
            get { return _RenewalSendDate; }

            set
            {
                if (AreDifferent(_RenewalSendDate, value))
                {
                    _RenewalSendDate = value;

                    StoreDirtyInformation(AreDifferent(DataContract.RenewalSendDate, value), PropertyName_RenewalSendDate);

                    FirePropertyChanged(PropertyName_RenewalSendDate);
                }
            }
        }

        public virtual DateTime? RequisitionSendDate
        {
            get { return _RequisitionSendDate; }

            set
            {
                if (AreDifferent(_RequisitionSendDate, value))
                {
                    _RequisitionSendDate = value;

                    StoreDirtyInformation(AreDifferent(DataContract.RequisitionSendDate, value), PropertyName_RequisitionSendDate);

                    FirePropertyChanged(PropertyName_RequisitionSendDate);
                }
            }
        }

        public virtual DateTime? SupportConceptSendDate
        {
            get { return _SupportConceptSendDate; }

            set
            {
                if (AreDifferent(_SupportConceptSendDate, value))
                {
                    _SupportConceptSendDate = value;

                    StoreDirtyInformation(AreDifferent(DataContract.SupportConceptSendDate, value), PropertyName_SupportConceptSendDate);

                    FirePropertyChanged(PropertyName_SupportConceptSendDate);
                }
            }
        }

        public GenericValueListEntryListVM CombinedGoals
        {
            get { return _CombinedGoals; }

            set
            {
                if (AreDifferent(_CombinedGoals, value))
                {
                    _CombinedGoals = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Goals, value), PropertyName_CombinedGoals);
                    FirePropertyChanged(PropertyName_CombinedGoals);
                }
            }
        }

        public TaskListVM Tasks
        {
            get { return _Tasks; }

            set
            {
                if (AreDifferent(_Tasks, value))
                {
                    _Tasks = value;
                    StoreDirtyInformation(AreDifferent(DataContract.Tasks, value), PropertyName_Tasks);
                    FirePropertyChanged(PropertyName_Tasks);
                }
            }
        }

        public void AddIndividualService(ServiceCategoryTreeItem parent)
        {
            var newItem = new ServiceCategoryTreeItem();
            //if (parent == null)
            //{
            //    ServiceCategoryDC newCategory = new ServiceCategoryDC();
            //    newCategory.Name = "Neue Kategorie";
            //    newItem.ServiceCategory = newCategory;
            //}
            //else
            //{
            var vm = _IndividualServices.NewVM;
            vm.ServiceDescription.Name = "Neue Leistung";
            vm.ServiceDescription.ScopeType = ScopeTypeId.Individual;
            newItem.ServiceAccountingVM = vm;
                //newSd.Category = parent.ServiceCategory;
                //parent.Children.Add(newItem);
                //newItem.Parent = parent;
            _IndividualServices.AddNewVMToList();
            //}

            IndividualServiceTree.Add(newItem);
        }

        internal void DeleteIndividualService(ServiceCategoryTreeItem selectedItem)
        {
            IndividualServiceTree.Remove(selectedItem);
            _IndividualServices.VMList.Remove(selectedItem.ServiceAccountingVM);
        }

        internal void DeleteIndividualGoal(SupportConceptGoalTreeItem selectedItem)
        {
            Children2Delete = new List<ValueListEntryDC>();
            TraverseCollection(selectedItem);

            var parent = selectedItem.ParentGoal as SupportConceptGoalTreeItem;

            if (parent != null && parent.Items != null)
                parent.Items.Remove(selectedItem);
            else
                CombinedGoalTree.Remove(selectedItem);

            CombinedGoals.VMList.Remove(selectedItem.GoalEntryVM);

            individualGoals2Delete= new List<long>();
            CollectGoals2Delete(selectedItem);

            foreach (var goal in CombinedGoalTree)
            {
                if (RemoveGoalFromGoalTree(goal, selectedItem))
                {
                    break;
                }
            }

            Goals.RemoveRange(Goals.Where(w => w.ValueListEntryOid.HasValue && individualGoals2Delete.Contains(w.ValueListEntryOid.Value)));
            _IndividualGoals.VMList.RemoveRange(_IndividualGoals.VMList.Where(w => !w.IsNew && w.DataContract.ValueListEntryOid.HasValue && individualGoals2Delete.Contains(w.DataContract.ValueListEntryOid.Value)));
        }

        private List<long> individualGoals2Delete;
        private void CollectGoals2Delete(SupportConceptGoalDC selectedItem)
        {
            if (selectedItem.GoalEntryDC != null && selectedItem.GoalEntryDC.ValueListEntryOid.HasValue)
            {
                individualGoals2Delete.Add(selectedItem.GoalEntryDC.ValueListEntryOid.Value);
            }

            foreach (var child in selectedItem.Children)
            {
                CollectGoals2Delete(child);
            }
        }

        private static bool RemoveGoalFromGoalTree(SupportConceptGoalDC currentGoal, SupportConceptGoalDC goal2Delete)
        {
            var shouldBreak = currentGoal.Children.Remove(goal2Delete);

            foreach (var child in currentGoal.Children)
            {
                shouldBreak = RemoveGoalFromGoalTree(child, goal2Delete);
            }

            return shouldBreak;
        }

        private void TraverseCollection(SupportConceptGoalTreeItem item)
        {
            var result = new List<ValueListEntryDC> { item.GoalEntryDC ?? item.GoalEntryVM.CommitToDataContract() };

            foreach (var child in item.Items)
            {
                TraverseCollection(child);
            }

            Children2Delete.AddRange(result);
        }

        public void AddZielOrMassnahme(SupportConceptGoalTreeItem parent, bool isCategory)
        {
            var newItem = new SupportConceptGoalTreeItem();
            var vm = _CombinedGoals.NewVM;
            vm.Type = isCategory ? ValueListEntryType.SupportConceptIndividualGoalCategoryType : ValueListEntryType.SupportConceptIndividualGoalType;
            vm.Description = isCategory ? "Neues individuelles Ziel" : "Neue individuelle Maßnahme";

            newItem.GoalEntryVM = vm;
            newItem.GoalEntryDC = vm.CommitToDataContract();

            _CombinedGoals.AddNewVMToList();
            newItem.ParentGoal = parent;

            CombinedGoalTree.Add(newItem);

            var vorhanden = CombinedGoals.VMList.Contains(newItem.GoalEntryVM);
            foreach (var item in CombinedGoalTree)
            {
                FindGoalVMInTreeView(item, newItem);
            }

            if (parent != null)
            {
                vm.ParentEntry = parent.GoalEntryDC ?? parent.GoalEntryVM.CommitToDataContract();
                parent.GoalEntryVM = parent.GoalEntryVM;
                parent.Items.Add(newItem);
                parent.IsExpanded = true;
            }
        }

        private bool TreeViewContainsVM;
        private void FindGoalVMInTreeView(SupportConceptGoalDC item, SupportConceptGoalDC wantedItem)
        {
            if (item.Children.Contains(wantedItem))
            {
                TreeViewContainsVM = true;
            }

            foreach (var child in item.Children)
            {
                FindGoalVMInTreeView(child, wantedItem);
            }
        }

        //public ServiceAccountingListVM ServiceAccountings
        //{
        //    get { return this._ServiceAccountings; }

        //    set
        //    {
        //        if (this.AreDifferent(this._ServiceAccountings, value))
        //        {
        //            this._ServiceAccountings = value;
        //            this.StoreDirtyInformation(this.AreDifferent(this.DataContract.ServiceAccountings, value), PropertyName_ServiceAccountings);
        //            this.FirePropertyChanged(PropertyName_ServiceAccountings);
        //        }
        //    }
        //}

        protected override void InitByDataContract(SupportConceptDC pDataContract)
        {
            //if (!IsNew)
            //{
                _Conference = pDataContract.Conference;
                _IsArchived = pDataContract.ActivationType == ActivationTypeId.Archived;
                _Originator = pDataContract.Originator;
                _Customer = pDataContract.Customer;
                _Notice = pDataContract.Notice;
                _ConferenceDate = pDataContract.ConferenceDate;
                _ApprovalDate = pDataContract.ApprovalDate;
                _RenewalSendDate = pDataContract.RenewalSendDate;
                _RequisitionSendDate = pDataContract.RequisitionSendDate;
                _SupportConceptSendDate = pDataContract.SupportConceptSendDate;
                _ConferenceVenue = pDataContract.ConferenceVenue;

                if (pDataContract.ConsultingNeeded == null)
                {
                    _ConsultingNeeded = false;
                }
                else
                {
                    _ConsultingNeeded = pDataContract.ConsultingNeeded.Value;
                }

                if (pDataContract.Goals != null)
                {
                    List<ValueListEntryDC> globalGoals =
                        pDataContract.Goals.FindAll(
							g => g.Type == ValueListEntryType.SupportConceptGoalType || g.Type == ValueListEntryType.SupportConceptGoalCategoryType);

                    List<ValueListEntryDC> individualGoals =
                        pDataContract.Goals.FindAll(
                            g => g.Type == ValueListEntryType.SupportConceptIndividualGoalType || g.Type == ValueListEntryType.SupportConceptIndividualGoalCategoryType);

                    _Goals = new ObservableSortCollection<ValueListEntryDC>(globalGoals, Comparer.ValueListEntryDCComparer);

                    _IndividualGoals = new GenericValueListEntryListVM(individualGoals);
                }

                Goals.CollectionChanged += (s, e) => StoreDirtyInformation(!_Goals.ContainsSameItemsAs(pDataContract.Goals), PropertyName_Goals);

                if (pDataContract.ServiceAccountings != null)
                {
                    List<ServiceAccountingDC> globalServices =
                        pDataContract.ServiceAccountings.FindAll(
                            sa => sa.ServiceDescription.ScopeType == ScopeTypeId.Global);

                    List<ServiceAccountingDC> individualServices =
                        pDataContract.ServiceAccountings.FindAll(
                            sa => sa.ServiceDescription.ScopeType == ScopeTypeId.Individual);

                    _SelectedGlobalServices = new ObservableSortCollection<ServiceAccountingDC>(globalServices, Comparer.ServiceAccountingDCComparer);


                    _IndividualServices = new ServiceAccountingListVM(individualServices);


                    //this._ServiceAccountings = new ServiceAccountingListVM(pDataContract.ServiceAccountings);
                }
            //}
            if (_IndividualGoals == null)
                _IndividualGoals = new GenericValueListEntryListVM(new List<ValueListEntryDC>());

            if (_IndividualServices == null)
                _IndividualServices = new ServiceAccountingListVM(new List<ServiceAccountingDC>());

            if (_SelectedGlobalServices == null)
                _SelectedGlobalServices = new ObservableSortCollection<ServiceAccountingDC>(Comparer.ServiceAccountingDCComparer);

            _SelectedGlobalServices.CollectionChanged += (s, e) => StoreDirtyInformation(_SelectedGlobalServices.Count > 0, PropertyName_GlobalServiceAccountings);

            _Tasks = new TaskListVM(pDataContract.Tasks);


            VMFactory.CreateSupportConceptCostBearerRelVMAsync(
                pDataContract.CostBearerRelations ?? (pDataContract.CostBearerRelations = new List<SupportConceptCostBearerRelDC>()),
                cb => _CostBearerRelations = cb);
        }

        protected override SupportConceptDC MapToDataContract(SupportConceptDC pDataContract, bool doCommit)
        {
            pDataContract.Conference = _Conference;
            pDataContract.ActivationType = _IsArchived ? ActivationTypeId.Archived : ActivationTypeId.Active;
            pDataContract.Originator = _Originator;
            pDataContract.Customer = _Customer;
            pDataContract.Notice = _Notice;
            pDataContract.ConferenceDate = _ConferenceDate;
            pDataContract.ApprovalDate = _ApprovalDate;
            pDataContract.RenewalSendDate = _RenewalSendDate;
            pDataContract.ConsultingNeeded = _ConsultingNeeded;
            pDataContract.RequisitionSendDate = _RequisitionSendDate;
            pDataContract.SupportConceptSendDate = _SupportConceptSendDate;
            pDataContract.ConferenceVenue = _ConferenceVenue;
            pDataContract.CostBearerRelations = _CostBearerRelations.CopyToDCList(doCommit);

            pDataContract.Tasks = Tasks.CopyToDCList(doCommit);

            pDataContract.ServiceAccountings = GetSelectedGlobalServices();

            if (_IndividualServices.VMList.Count > 0)
            {
                if (pDataContract.ServiceAccountings == null)
                    pDataContract.ServiceAccountings = new List<ServiceAccountingDC>();
                pDataContract.ServiceAccountings.AddRange(_IndividualServices.CopyToDCList(doCommit));
            }

            pDataContract.Goals = GetSelectedGoals();

            return pDataContract;
        }

        private List<ValueListEntryDC> GetSelectedGoals()
        {
            selectedGoals = new List<ValueListEntryDC>();

            var vms = CombinedGoals.VMList.Where(w => (w.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalType) || w.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalCategoryType)) && w.IsNew);
            
            foreach (var item in _CombinedGoalTree)
            {
                IterateThroughSelectedGoalsAndMassnahmen(item);
            }

            selectedGoals.AddRange(vms.Select(s => s.CommitToDataContract()));

            return selectedGoals;
        }

        
        public void IterateThroughSelectedGoalsAndMassnahmen(SupportConceptGoalDC category)
        {
	        if ((category.IsChecked && category.GoalEntryDC.Type.Equals(ValueListEntryType.SupportConceptGoalType)) || 
                (((category.GoalEntryDC.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalType) || category.GoalEntryDC.Type.Equals(ValueListEntryType.SupportConceptIndividualGoalCategoryType)) && category.GoalEntryDC.ValueListEntryOid != null))
				|| category.IsChecked && category.Children.Count == 0)
			{
                selectedGoals.Add(category.GoalEntryDC);
            }

            foreach (var item in category.Children)
            {
                IterateThroughSelectedGoalsAndMassnahmen(item);
            }
        }

        public List<SupportConceptGoalTreeItem> TreeViewItemsList;
        public void GetAllTreeViewItems()
        {
            foreach (var parent in CombinedGoalTree.Where(w => !w.HasParent))
            {
                TraverseTreeViewItem(parent);
            }
        }

        private void TraverseTreeViewItem(SupportConceptGoalTreeItem item)
        {
            TreeViewItemsList.Add(item);
            foreach (var child in item.Items)
            {
                TraverseTreeViewItem(child);
            }
        }

        private List<ServiceAccountingDC> GetSelectedGlobalServices()
        {
            var services = new List<ServiceAccountingDC>();
            var everyItemChecked = true;
            foreach (var item in GlobalServiceTree)
            {
                foreach (var child in item.Children)
                {
                    if (child.IsChecked)
                    {
                        services.Add(child.ServiceAccounting);
                    } else
                    {
                        everyItemChecked = false;
                    }
                }
            }

            return everyItemChecked ? null : services;
        }

        private void GlobalServiceTreeItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var treeItem = sender as ServiceCategoryTreeItem;
            if (treeItem != null && treeItem.ServiceAccounting != null)
            {
                if (treeItem.IsChecked)
                {
                    SelectedGlobalServices.Add(treeItem.ServiceAccounting);
                }
                else
                {
                    if (_SelectedGlobalServices.Count == 0) //Wenn alle gecheckt sind, erst mal alle zufügen
                    {
                        foreach (var sc in GlobalServiceTree)
                        {
                            foreach (var child in sc.Children)
                            {
                                if (child.ServiceAccounting != null)
                                    SelectedGlobalServices.Add(child.ServiceAccounting);
                            }
                        }
                    }

                    SelectedGlobalServices.Remove(treeItem.ServiceAccounting);
                }
            }
        }
    }
}