using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Navigation;

using BeWo.Converter;
using BeWo.Core;
using BeWo.Security;
using BeWo.ServiceProxy;
using BeWo.View.Navigation.Filter;

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

namespace BeWo.View.Navigation
{
    public partial class MainNavigationView : INotifyPropertyChanged
    {
        internal CustomFilter _CustomFilter;

        private readonly string _DetailsLoadLock = string.Empty;

        private bool _DetailsLoadRunning;

        private IFilterableDC _SelectedItem;

        private bool _ShowDetailPanel;

        private AbstractSorter mSorter;

        public MainNavigationView()
        {
            InitializeComponent();

            ArchiveButtonVisible = false;
            sortPanel.Visibility = Visibility.Collapsed;

            DownloadLinkEngine = new DownloadLinkEngine();
            linkExcelExport.NavigateUri = DownloadLinkEngine.GenerateNewExcelLink();

            objectHistoryListBox.SelectionChanged += (s, e) =>
                {
                    if (e.AddedItems.Count > 0)
                    {
                        objectListBox.SelectedIndex = -1;
                    }
                };
            objectListBox.SelectionChanged += (s, e) =>
                {
                    if (e.AddedItems.Count > 0)
                    {
                        objectHistoryListBox.SelectedIndex = -1;
                    }
                };

            textbox_search.PreviewKeyDown += (s, e) =>
                {
                    if (e.Key == Key.Enter)
                    {
                        OpenSelectedObject();
                    }
                    else if (e.Key == Key.Down)
                    {
                        objectListBox.Focus();
                    }
                };

            objectListBox.PreviewKeyDown += (s, e) =>
                {
                    if (e.Key == Key.Enter)
                    {
                        OpenSelectedObject();
                    }
                };
        }

        public delegate bool ArchiveObjectDelegate(IFilterableDC obj);

        public delegate void CreateNewObjectDelegate();

        public delegate bool DeleteObjectDelegate(IFilterableDC obj);

        public delegate void OpenObjectDelegate(IFilterableDC obj);

        public delegate void ReloadDataDelegate();

        public delegate void OpenMailMergeWindowDelegate(List<IFilterableDC> allObjects, IFilterableDC selectedObject);

	    public delegate void CopyObjectDelegate(IFilterableDC obj);

        public event ArchiveObjectDelegate ArchiveObject;

        public event CreateNewObjectDelegate CreateNewObject;

        public event DeleteObjectDelegate DeleteObject;

        public event EventHandler<EventArgs<IEnumerable<IFilterableDC>>> ExcelExport;

        public event OpenObjectDelegate OpenObject;

        public event ReloadDataDelegate OnReloadData;

        public event OpenMailMergeWindowDelegate OpenMailMergeWindow;

        public event PropertyChangedEventHandler PropertyChanged;

	    public event CopyObjectDelegate CopyObject;

        public bool ArchiveButtonVisible
        {
            get
            {
                return btnArchive.Visibility == Visibility.Visible;
            }

            set
            {
                btnArchive.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public Style ContentGroupStyle
        {
            get
            {
                return contentGroup.Style;
            }

            set
            {
                contentGroup.Style = value;
            }
        }

        [TypeConverter(typeof(UserRightTypeArrayConverter))]
        public UserRightType[] CreateDemands
        {
            set
            {
                DemandUserRight.SetVisibleDemands(btnNew, value);
            }
        }

        public CustomFilter CustomFilter
        {
            get
            {
                return _CustomFilter;
            }

            set
            {
                _CustomFilter = value;

                FirePropertyChanged("CustomFilter");

                // if (listBoxMultiBinding.Bindings.Count == 4)
                // listBoxMultiBinding.Bindings.RemoveAt(3);

                // if (customFilter != null) 
                // {
                // MultiBinding mb = BindingOperations.GetMultiBinding(objectListBox, System.Windows.Controls.ListBox.ItemsSourceProperty);
                // BindingOperations.ClearBinding(objectListBox, System.Windows.Controls.ListBox.ItemsSourceProperty);

                // MultiBinding newMb = new MultiBinding();
                // newMb.Converter = mb.Converter;

                // foreach (var b in mb.Bindings)
                // {
                // newMb.Bindings.Add(b);
                // }

                // Binding binding = new Binding();
                // binding.Source = customFilter;
                // binding.Mode = BindingMode.OneWay;

                // newMb.Bindings.Add(binding);

                // objectListBox.SetBinding(System.Windows.Controls.ListBox.ItemsSourceProperty, newMb);

                // // objectListBox.ItemsSource = mb;
                // }
            }
        }

        public bool DeleteButtonVisible
        {
            get
            {
                return btnDelete.Visibility == Visibility.Visible;
            }

            set
            {
                btnDelete.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        [TypeConverter(typeof(UserRightTypeArrayConverter))]
        public UserRightType[] DeleteDemands
        {
            set
            {
                DemandUserRight.SetVisibleDemands(btnDelete, value);
            }
        }

        public DataTemplate DetailPanelItemTemplate
        {
            get
            {
                return details_presenter.ContentTemplate;
            }

            set
            {
                details_presenter.ContentTemplate = value;
            }
        }

        public DownloadLinkEngine DownloadLinkEngine { get; set; }

        public bool EditButtonsVisible
        {
            get
            {
                return btnNew.Visibility == Visibility.Visible;
            }

            set
            {
                btnNew.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
                DeleteButtonVisible = value;
                ArchiveButtonVisible = value;
            }
        }

        public Style HistoryListItemStyle
        {
            set
            {
                objectHistoryListBox.ItemContainerStyle = value;
            }
        }

        public object MainGroupHeader
        {
            get
            {
                return mainGroup.Header;
            }

            set
            {
                mainGroup.Header        = value;
                chkShowArchived.Content = " Archivierte " + value + " anzeigen";
				chkShowDeleted.Content  = " Gelöschte " + value + " anzeigen";
            }
        }

        public Style MainListItemStyle
        {
            set
            {
                objectListBox.ItemContainerStyle = value;
            }
        }

        public bool ShowArchivedObjectsVisible
        {
            get
            {
                return chkShowArchived.Visibility == Visibility.Visible;
            }

            set
            {
                chkShowArchived.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public bool ShowDetailsPanel
        {
            get
            {
                return _ShowDetailPanel;
            }

            set
            {
                _ShowDetailPanel = value;
                stackPanle_details.Visibility = value ? Visibility.Visible : Visibility.Hidden;
            }
        }

        public AbstractSorter Sorter
        {
            get
            {
                return mSorter;
            }

            set
            {
                mSorter = value;
                sortCombo.Items.Clear();

                if (mSorter != null)
                {
                    sortPanel.Visibility = mSorter.SortItems.Count > 0 ? Visibility.Visible : Visibility.Collapsed;

                    foreach (SortItem item in mSorter.SortItems)
                    {
                        sortCombo.Items.Add(item);
                    }

                    sortCombo.SelectedIndex = 0;
                }
            }
        }

        public void AddControlToSortPanel(UIElement element)
        {
            sortPanel.Children.Add(element);
        }

        public void OnDetailsLoadedCompleted(object details, object item)
        {
            this.Dispatch(delegate { details_presenter.DataContext = details; });

            lock (_DetailsLoadLock)
            {
                if (!Equals(_SelectedItem, item))
                {
                    if (_SelectedItem is CompactSupportConceptDC)
                    {
                        var dc = _SelectedItem as CompactSupportConceptDC;
                        ServiceFacade.DoOperationsServiceAsyncNoWait(
                            s => s.GetSupportConceptInfosForSupportConceptOid(dc.SupportConceptOid),
                            OnDetailsLoadedCompleted, dc);
                    }
                    else if (_SelectedItem is CompactCustomerDC)
                    {
                        var dc = _SelectedItem as CompactCustomerDC;
                        ServiceFacade.DoOperationsServiceAsyncNoWait(
                            s => s.GetCustomerInfosForCustomerOid(dc.CustomerOid), OnDetailsLoadedCompleted, dc);
                    }
                }
                else
                {
                    _DetailsLoadRunning = false;
                }
            }
        }

        public void ShowHistory(IEnumerable<IFilterableDC> result)
        {
            objectHistoryListBox.ItemsSource = result.ToObservableSortCollection();
        }

        public void ShowSearchResult(IEnumerable<IFilterableDC> result)
        {
            SortSearchResult(result);
        }

        public void SortSearchResult(IEnumerable<IFilterableDC> result)
        {
            if (mSorter == null)
            {
                objectListBox.DataContext = result.ToObservableSortCollection();
            }
            else
            {
                var item = sortCombo.SelectedItem as SortItem;
                if (item != null)
                {
                    SortSearchResult(item, result);
                }
            }
        }

        public void SortSearchResult(SortItem item, IEnumerable<IFilterableDC> result)
        {
            if (mSorter != null && item != null)
            {
                var items = result;

                if (items != null)
                {
                    var dir = AbstractSorter.SortDirection.Ascending;
                    if (sortDirectionToggleButton.IsChecked != null && sortDirectionToggleButton.IsChecked.Value)
                    {
                        dir = AbstractSorter.SortDirection.Descending;
                    }

                    objectListBox.DataContext = items.ToObservableSortCollection(mSorter.GetComparison(item, dir));
                }
            }
        }

        protected virtual void FirePropertyChanged(string pPropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(pPropertyName));
            }
        }

        private void ExcelCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            // e.CanExecute = listPerson.Items.Count > 0;
        }

        private void ExcelCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            // bool lRes = lClient.PrepareExcelFile((string)e.Parameter, listPerson.GetHeader(), listPerson.GetContent());
            // ProxyFactory.CloseDownloadServiceClient.Close();
        }

        private bool IsPartOf(object p, Type type)
        {
            if (p != null)
            {
                var fe = p as FrameworkElement;
                if (fe != null)
                {
                    if (fe.GetType() == type)
                    {
                        return true;
                    }

                    return IsPartOf(fe.TemplatedParent, type);
                }
            }

            return false;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            textbox_search.Focus();
        }

        private void OnOpenObject()
        {
            if (OpenObject != null)
            {
                object obj = objectListBox.SelectedItem ?? objectHistoryListBox.SelectedItem;

                if (obj is IFilterableDC)
                {
                    OpenObject(obj as IFilterableDC);
                }
            }
        }

        private void OnOpenMailMergeWindow()
        {
            if (OpenMailMergeWindow == null) return;

            object allObjects = objectListBox.Items;
            var selectedObject = objectListBox.SelectedItem;

            OpenMailMergeWindow(allObjects as List<IFilterableDC>, selectedObject as IFilterableDC);
        }

        private void OpenCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            // e.CanExecute = listPerson.SelectedItem != null;
        }

        private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            // CompactPersonDC lPerson = listPerson.SelectedItem as CompactPersonDC;

            // if (lPerson != null && PersonSelected != null)
            // PersonSelected(this, new EventArgs<CompactPersonDC>(lPerson));
        }

        private void OpenSelectedObject()
        {
            if (OpenObject != null)
            {
                object selectedObj = objectListBox.SelectedItem;
                if (selectedObj == null)
                {
                    IEnumerator enu = objectListBox.ItemsSource.GetEnumerator();
                    enu.MoveNext();
                    selectedObj = enu.Current;
                }

                if (selectedObj != null && selectedObj is IFilterableDC)
                {
                    OpenObject(selectedObj as IFilterableDC);
                }
            }
        }

        private void btnArchive_Click(object sender, RoutedEventArgs e)
        {
            if (ArchiveObject != null)
            {
                var obj = objectListBox.SelectedItem as IFilterableDC;
                if (obj != null)
                {
                    if (ArchiveObject(obj))
                    {
                        obj.ActivationType = ActivationTypeId.Archived;
                        object test = objectListBox.DataContext;
                        objectListBox.DataContext = null;
                        objectListBox.DataContext = test;
                    }
                }
            }
        }

        private void btnDelete_Click(object sender, RoutedEventArgs e)
        {
            if (DeleteObject != null)
            {
                var obj = objectListBox.SelectedItem as IFilterableDC;

                if (obj != null)
                {
                    if (DeleteObject(obj))
                    {
                        object test = objectListBox.DataContext;

                        //((ObservableCollection<IFilterableDC>)test).Remove(obj);
	                    obj.ActivationType = ActivationTypeId.Deleted;
                        objectListBox.DataContext = null;
                        objectListBox.DataContext = test;
                        ((ObservableCollection<IFilterableDC>)objectHistoryListBox.ItemsSource).Remove(obj);
                    }
                }
            }
        }

        private void btnEdit_Click(object sender, RoutedEventArgs e)
        {
            OnOpenObject();
        }

        private void btnNew_Click(object sender, RoutedEventArgs e)
        {
            if (CreateNewObject != null)
            {
                CreateNewObject();
            }
        }

	    private void btnCopy_Click(object sender, RoutedEventArgs e)
	    {
		    if (CopyObject != null)
		    {
			    var obj = objectListBox.SelectedItem as IFilterableDC;

			    if (obj != null)
			    {
				    CopyObject(obj);
			    }
		    }
	    }

        private ObservableSortCollection<IFilterableDC> GetFilteredList(ObservableSortCollection<IFilterableDC> results)
        {
            if (chkShowArchived.IsChecked != null && (chkShowArchived.Visibility == Visibility.Visible && !chkShowArchived.IsChecked.Value))
            {
                if (results.Count > 0)
                {
                    IFilterableDC firstDC = results[0];
                    if (firstDC.SupportsActivationType)
                    {
                        var filteredList = new ObservableSortCollection<IFilterableDC>();
                        foreach (IFilterableDC dc in results)
                        {
                            if (dc.ActivationType == ActivationTypeId.Active)
                            {
                                filteredList.Add(dc);
                            }
                        }

                        return filteredList;
                    }
                }
            }

            return results;
        }

        private void linkExcelExport_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            if (ExcelExport != null)
                ExcelExport(this, new EventArgs<IEnumerable<IFilterableDC>>(objectListBox.ItemsSource as IEnumerable<IFilterableDC>));
        }

        private void objectHistoryListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            OnOpenObject();
        }

        private void objectListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (!IsPartOf(e.OriginalSource, typeof (ScrollBar)))
            {
                OnOpenObject();
            }
        }

        private void objectListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var lb = (ListBox)sender;
            if (lb.SelectedItem != null)
            {
                lock (_DetailsLoadLock)
                {
                    _SelectedItem = lb.SelectedItem as IFilterableDC;

                    if (!_DetailsLoadRunning)
                    {
                        if (_SelectedItem is CompactSupportConceptDC)
                        {
                            var dc = _SelectedItem as CompactSupportConceptDC;
                            ServiceFacade.DoOperationsServiceAsyncNoWait(s => s.GetSupportConceptInfosForSupportConceptOid(dc.SupportConceptOid),
                                OnDetailsLoadedCompleted, dc);

                            _DetailsLoadRunning = true;
                        }
                        else if (_SelectedItem is CompactCustomerDC)
                        {
                            var dc = _SelectedItem as CompactCustomerDC;

                            ServiceFacade.DoOperationsServiceAsyncNoWait(s => s.GetCustomerInfosForCustomerOid(dc.CustomerOid), OnDetailsLoadedCompleted, dc);
                            _DetailsLoadRunning = true;
                        }
                    }
                }
            }
            else
            {
                details_presenter.DataContext = null;
            }
        }

        private void sortCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                SortSearchResult(e.AddedItems[0] as SortItem, objectListBox.ItemsSource as IEnumerable<IFilterableDC>);
            }
        }

        private void sortDirectionToggleButton_Click(object sender, RoutedEventArgs e)
        {
            SortSearchResult(objectListBox.ItemsSource as IEnumerable<IFilterableDC>);
        }

        private void ReloadButton_OnClick(object sender, RoutedEventArgs e)
        {
            if (OnReloadData != null)
                OnReloadData();
        }

        private void btnMailMerge_Click(object sender, RoutedEventArgs e)
        {
            OnOpenMailMergeWindow();
        }
    }
}