using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

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

using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.ClientPartials;
using BS.Shared.Extensions;

namespace BeWo.View.Detail
{
    public partial class MassnahmenTreeViewView
    {
        private TreeViewItem _SelectedGoalTreeNode;

        public static bool IsAllowedToEditGoals
        {
            get { return BeWoApp.LoggedOnUser.HasRight(UserRightType.SupportConcept_AllowEditGoals); }
        }

        private GenericValueListEntryListVM viewModel;

        public GenericValueListEntryListVM ViewModel
        {
            get { return viewModel; }
            set
            {
                viewModel = value;
                InitGoalCategoriesTreeView();
                treeview_individualGoals.ItemsSource = GoalTree;
            }
        }

        public ObservableSortCollection<SupportConceptGoalTreeItem> GoalTree { get; private set; }

        public MassnahmenTreeViewView(GenericValueListEntryListVM pViewModel)
        {
            InitializeComponent();

            ViewModel = pViewModel;

            DataContext = this;
        }

        public override bool IsDirty
        {
            get
            {
                return ViewModel != null && ViewModel.IsDirty;
            }
        }

        protected override void Save()
        {
            var lToDos = new List<Action<IValueListService>>();

            if (ViewModel.ChangedCount > 0)
            {
                lToDos.Add(s => s.UpdateValueListEntries(ViewModel.CommitChanged()));
            }

            if (ViewModel.AddedCount > 0)
            {
                var neueVMs = ViewModel.VMList.Where(w => w.IsNew).ToList();

                TreeViewItemsList = new List<SupportConceptGoalTreeItem>();
                GetAllTreeViewItems();

                var obersteZiele = neueVMs.Where(w => w.IsNew && (w.ParentEntry != null && w.ParentEntry.ValueListEntryOid != null) || w.ParentEntry == null);

                foreach (var ziel in obersteZiele)
                {
	                var ve = TreeViewItemsList.FirstOrDefault(f => f.GoalEntryVM != null && f.GoalEntryVM.Equals(ziel));
	                if (ve != null)
	                {
		                GoalService.RecursiveSynchronousValueListEntrySave(ve);
	                }
                }
            }

            if (ViewModel.RemovedCount > 0)
            {
                var entfernte = Children2Delete.Where(w => w.ValueListEntryOid != null).ToList();
                var entfernteDic = entfernte.ToDictionary(k => k.ValueListEntryOid.Value, v => v.ValueListEntryVersion.Value);
                entfernteDic.AddAndIgnoreDuplicates(ViewModel.GetRemoved().ToDictionary(dc => dc.ValueListEntryOid.Value, dc => dc.ValueListEntryVersion.Value));

                lToDos.Add(s => s.DeactivateValueListEntries(entfernteDic));
            }

            ServiceFacade.DoMultipleValueListServicesAsync(lToDos, ReloadViewModel);

			Cache.GetInstance().ClearAllValueListEntries();
        }

	    private bool IstGleichesZiel(ValueListEntryVM ziel1, ValueListEntryVM ziel2)
	    {
		    if (ziel1.DataContract.ValueListEntryOid.HasValue && ziel2.DataContract.ValueListEntryOid.HasValue)
		    {
			    return ziel1.DataContract.ValueListEntryOid.Value == ziel2.DataContract.ValueListEntryOid.Value;
		    }
			else if (!ziel1.DataContract.ValueListEntryOid.HasValue && !ziel2.DataContract.ValueListEntryOid.HasValue)
			{
				if (ziel1.ParentEntry != null && ziel2.ParentEntry != null && ziel1.ParentEntry.Equals(ziel1.ParentEntry))
				{
					bool test = ziel1.Equals(ziel2);
					return ziel1.Description == ziel2.Description;
				}
				else if (ziel1.ParentEntry == null && ziel2.ParentEntry == null)
				{
					return ziel1.Description == ziel2.Description;
				}
			}
		    return false;
	    }

        private void ReloadViewModel()
        {
            VMFactory.CreateGoalCategoryVMAsync(vm => this.Dispatch(() =>
            {
                ViewModel = vm;
            }));
        }

        private void GoalTreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            var source = e.OriginalSource as DependencyObject;
            while (source != null && !(source is TreeViewItem))
            {
                source = VisualTreeHelper.GetParent(source);
            }

            if (source != null)
            {
                ((TreeViewItem)source).IsSelected = true;
                _SelectedGoalTreeNode = (TreeViewItem)source;
            }
            else
            {
                _SelectedGoalTreeNode = null;
            }
        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            UpdateSelectedTreeItemText((TextBox)sender);
        }

        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                UpdateSelectedTreeItemText((TextBox)sender);
            }
        }

        private void ContextMenuGoals_Click(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is MenuItem)
            {
                var twi = e.OriginalSource as MenuItem;

                var selectedItem = treeview_individualGoals.SelectedItem as SupportConceptGoalTreeItem;

                if (twi.Header.Equals("Neue Maßnahme"))
                {
                    if (_SelectedGoalTreeNode != null)
                    {
                        _SelectedGoalTreeNode.ItemContainerGenerator.StatusChanged +=
                            GoalTreeItemContainerGenerator_StatusChanged;

                        AddMassnahme(selectedItem);
                    }
                }
                else if (twi.Header.Equals("Neues Ziel"))
                {
                    if (_SelectedGoalTreeNode != null)
                    {
                        _SelectedGoalTreeNode.ItemContainerGenerator.StatusChanged +=
                            GoalTreeItemContainerGenerator_StatusChanged;

                        AddZiel(selectedItem);
                    }
                }
                else if (twi.Header.Equals("Umbenennen"))
                {
                    EditItem(treeview_individualGoals, _SelectedGoalTreeNode, selectedItem);
                }
                else if (twi.Header.Equals("Löschen"))
                {
                    if (selectedItem != null)
                    {
                        var zielOderMassnahme = selectedItem.GoalEntryVM.Type == ValueListEntryType.SupportConceptGoalCategoryType ? "das Ziel" : "die Maßnahme";
                        var pluralendung = zielOderMassnahme.Equals("das Ziel") ? "en" : "n";

                        if (MessageBox.Show("ACHTUNG: Das Löschen von " + zielOderMassnahme.Substring(4) + pluralendung + " kann nicht rückgängig gemacht werden.\n" +
                                                                    "Alle verknüpften Eintragungen in der Zeiterfassung bleiben erhalten.\n\n" +
                                                                    "Wollen Sie " + zielOderMassnahme + " '" + selectedItem.ItemName + "' wirklich löschen?", "Löschen bestätigen", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                        {
                            DeleteIndividualGoal(selectedItem);
                        }
                    }
                }
            }
        }

        private void ContextMenuGoals_Opened(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is ContextMenu)
            {
                var menu = e.OriginalSource as ContextMenu;
                var goal = treeview_individualGoals.SelectedItem as SupportConceptGoalTreeItem;

                foreach (var menuitem in menu.Items.OfType<MenuItem>().Select(item => item))
                {
                    if (menuitem.Header.Equals("Neue Maßnahme"))
                        menuitem.IsEnabled = goal != null && !goal.IsGoal;
                    else if (menuitem.Header.Equals("Neues Ziel"))
                        menuitem.IsEnabled = goal != null && !goal.IsGoal;

                    menuitem.IsEnabled = menuitem.IsEnabled && IsAllowedToEditGoals;
                }
            }
        }

        private static void EditItem(TreeView tv, TreeViewItem tvi, object item)
        {
            if (item != null)
            {
                var treeItem = tvi;
                if (treeItem == null && tv != null)
                    treeItem = tv.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

                if (treeItem != null)
                {
                    var textBox = BeWoWpfUtils.FindVisualChild<TextBox>(treeItem);
                    textBox.IsReadOnly = false;
                    textBox.Padding = new Thickness(1, 1, 1, 1);
                    textBox.BorderThickness = new Thickness(1);
                    textBox.Background = Brushes.White;
                    textBox.Tag = tv.SelectedItem;
                    textBox.Focus();
                    textBox.SelectAll();
                }
            }
        }

        private void GoalTreeItemContainerGenerator_StatusChanged(object sender, EventArgs e)
        {
            var ig = (ItemContainerGenerator)sender;
            if (ig.Status != GeneratorStatus.ContainersGenerated)
            {
                return;
            }

            var n = ig.ContainerFromIndex(_SelectedGoalTreeNode.Items.Count - 1) as TreeViewItem;
            if (n != null)
            {
                n.IsSelected = true;

                new DispatcherTimer(
                    TimeSpan.FromMilliseconds(200),
                    DispatcherPriority.Background,
                    (s1, e1) =>
                    {
                        _SelectedGoalTreeNode = n;
                        var item = ig.ItemFromContainer(n) as SupportConceptGoalDC;
                        EditItem(treeview_individualGoals, _SelectedGoalTreeNode, item);
                        ((DispatcherTimer)s1).Stop();
                    },
                    Dispatcher).Start();
            }

            _SelectedGoalTreeNode.ItemContainerGenerator.StatusChanged -= GoalTreeItemContainerGenerator_StatusChanged;
        }

        private static void UpdateSelectedTreeItemText(TextBox textBox)
        {
            if (!textBox.IsReadOnly)
            {
                textBox.Background = Brushes.Transparent;
                textBox.IsReadOnly = true;
                textBox.BorderThickness = new Thickness(0);
                textBox.Padding = new Thickness(1, 3, 1, 3);
            }
        }

        private void InitGoalCategoriesTreeView()
        {
            var categoriesWithParent = new List<SupportConceptGoalTreeItem>();
            var goalList = GoalService.GetZieleMassnahmenTree(ViewModel.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 = ViewModel.VMList.FirstOrDefault(f => f.DataContract.ValueListEntryOid.Value == category.GoalEntryDC.ValueListEntryOid.Value),
                    IsExpanded = true,
                    ParentGoal = category.ParentGoal
                };
                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;

                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)
            {
                dictOid2TreeItem[goalCategory.GoalEntryDC.ParentOid.Value].Children.Add(goalCategory);
            }

            foreach (var goal in ViewModel.VMList.Where(w => w.Type.Equals(ValueListEntryType.SupportConceptGoalType)))
            {
                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;
                }
            }

            GoalTree = iGoalList;
        }

        private List<ValueListEntryDC> Children2Delete;
        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
                GoalTree.Remove(selectedItem);

            ViewModel.VMList.Remove(selectedItem.GoalEntryVM);
        }

        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 AddMassnahme(SupportConceptGoalTreeItem parent)
        {
            var newItem = new SupportConceptGoalTreeItem();
            var vm = ViewModel.NewVM;
            vm.Type = ValueListEntryType.SupportConceptGoalType;
            vm.Description = "Neue Maßnahme";

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

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

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

        public void AddZiel(SupportConceptGoalTreeItem parent)
        {
            var newItem = new SupportConceptGoalTreeItem();
            var vm = ViewModel.NewVM;
            vm.Type = ValueListEntryType.SupportConceptGoalCategoryType;
            vm.Description = "Neues Ziel";

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

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

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

        private List<SupportConceptGoalTreeItem> TreeViewItemsList;
        private void GetAllTreeViewItems()
        {
            foreach (var parent in GoalTree)
            {
                TraverseTreeViewItem(parent);
            }
        }

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

        private void ZielHinzufuegenButton_Click(object sender, RoutedEventArgs e)
        {
            var newItem = new SupportConceptGoalTreeItem();
            var vm = ViewModel.NewVM;
            vm.Type = ValueListEntryType.SupportConceptGoalCategoryType;

            newItem.GoalEntryVM = vm;
            ViewModel.AddNewVMToList();

            GoalTree.Add(newItem);

            GoalTree.Sort((x, y) =>
            {
	            if (x.ItemName == null)
		            return String.Empty.CompareTo(y.ItemName);
	            return x.ItemName.CompareTo(y.ItemName);
            });
        }
    }

    public class ValueListEntryTypeToFontWeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var val = (bool)value;

            return val ? FontWeights.Normal : FontWeights.Bold;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
