using Dragablz;
using PDF_Office.EventAggregators;
using PDF_Office.Views;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace PDF_Office.CustomControl.SystemControl
{
    public class DragablzWindowBehavior : RegionBehavior
    {
        public const string BehaviorKey = "DragablzWindowBehavior";

        private TabablzControl activeTabcontrol;
        private readonly ObservableCollection<TabablzControl> tabcontrols;

        public DragablzWindowBehavior()
        {
            this.tabcontrols = new ObservableCollection<TabablzControl>();
        }

        protected override void OnAttach()
        {
            this.Region.Views.CollectionChanged += Views_CollectionChanged;
            this.Region.ActiveViews.CollectionChanged += ActiveViews_CollectionChanged;
            var eventAggregator = Prism.Ioc.ContainerLocator.Container.Resolve(typeof(IEventAggregator)) as IEventAggregator;
            eventAggregator.GetEvent<DragablzWindowEvent>().Subscribe(OnDragablzWindowEvent);
        }

        public void OnDragablzWindowEvent(DragablzWindowEventArgs args)
        {
            switch (args.Type)
            {
                case DragablzWindowEventType.Opened:
                    OnWindowOpened(args.TabControl);
                    break;

                case DragablzWindowEventType.Closed:
                    OnWindowClosed(args.TabControl);
                    break;

                case DragablzWindowEventType.Activated:
                    OnWindowActivated(args.TabControl);
                    break;
            }
        }

        private void OnWindowActivated(TabablzControl tabControl)
        {
            if (this.activeTabcontrol != tabControl)
            {
                SetActiveView(tabControl);
            }
        }

        private void OnWindowClosed(TabablzControl tabControl)
        {
            ClearRelatedTabs(tabControl);
            this.tabcontrols.Remove(tabControl);
            tabControl.SelectionChanged -= TabControl_SelectionChanged;

            if (this.activeTabcontrol == tabControl)
            {
                this.activeTabcontrol = this.tabcontrols.FirstOrDefault();
            }
        }

        private void ClearRelatedTabs(TabablzControl tabControl)
        {
            var items = tabControl.Items.OfType<MainContent>().ToList();

            items.ForEach(item =>
            {
                try
                {
                    this.Region.Remove(item.Content);
                }
                catch (ArgumentException) { }
            });
        }

        private void OnWindowOpened(TabablzControl tabControl)
        {
            this.activeTabcontrol = tabControl;
            this.tabcontrols.Add(tabControl);
            tabControl.ClosingItemCallback = ClosingItemCallback;
            tabControl.SelectionChanged += TabControl_SelectionChanged;
        }

        private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                var item = e.AddedItems[0] as MainContent;
                if (item != null)
                {
                    var regionItem = item.Content;

                    if (this.Region.Views.Contains(regionItem))
                    {
                        this.Region.Activate(regionItem);
                    }
                }
            }
        }


        private void ClosingItemCallback(ItemActionCallbackArgs<TabablzControl> args)
        {
            //remove from region
                this.Region.Remove(((MainContent)args.DragablzItem.Content));
        }

        private void ActiveViews_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    ActivateView(e.NewItems[0]);

                    break;
            }
        }

        private void Views_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    AddView(e.NewItems[0]);
                    break;

                case NotifyCollectionChangedAction.Remove:
                    RemoveView(e.OldItems[0]);
                    break;
            }
        }

        public void ActivateView(object view)
        {
            var proxy = GetView(view);
            var tabcontrol = GetTabcontrol(view);

            if (tabcontrol.SelectedItem != proxy || tabcontrol != this.activeTabcontrol)
            {
                tabcontrol.SelectedItem = proxy;
                tabcontrol.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            }
        }

        private void SetActiveView(TabablzControl window)
        {
            if (this.activeTabcontrol != window)
            {
                this.activeTabcontrol = window;
                this.activeTabcontrol.BringIntoView();
                this.activeTabcontrol.Focus();

                var view = this.activeTabcontrol.SelectedItem as MainContent;
                if (view != null && this.Region.Views.Contains(view.Content))
                {
                    this.Region.Activate(view.Content);
                }
            }
        }

        private void RemoveView(object view)
        {
            var tabcontrol = GetTabcontrol(view);
            var proxy = GetView(view);
            tabcontrol.Items.Remove(proxy);
            if(tabcontrol.Items.Count<=0)
            {
                (Window.GetWindow(tabcontrol) as MainWindow).Close();
            }
        }

        private void AddView(object view)
        {
            activeTabcontrol = (App.Current.MainWindow as MainWindow).TabablzControl;
            var item = view as MainContent;
            if (item != null)
            {
                this.activeTabcontrol.Items.Add(item);
                this.activeTabcontrol.SelectedItem = item;
            }
        }

        private TabablzControl GetTabcontrol(object view)
        {
            var proxy = GetView(view);

            foreach (var window in this.tabcontrols)
            {
                if (ContainsView(window, proxy))
                {
                    return window;
                }
            }

            return null;
        }

        private bool ContainsView(TabablzControl window, MainContent proxy)
        {
            if (proxy == null || window == null) return false;

            return window.Items.OfType<MainContent>().Any(tc => tc == proxy);
        }

        private MainContent GetView(object view)
        {
            return view as MainContent;
        }
    }
}
