using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Xaml.Behaviors.Core;

namespace InABox.DynamicGrid
{

    public class DynamicTabControlEventArgs : CancelEventArgs
    {
        public DynamicTabItem TabItem { get; set; }
    }    
    
    public class DynamicTabItemContextMenuEventArgs : CancelEventArgs
    {
        public ContextMenu Menu { get; set; }
    }

    public class DynamicTabItemRenamedEventArgs : CancelEventArgs
    {
        public String OldName { get; set; }
        public String NewName { get; set; }
    }

    public delegate void DynamicTabControlChangedEvent(object sender, EventArgs args);
    
    public delegate void DynamicTabControlCreateEvent(object sender, DynamicTabControlEventArgs args);
    
    public delegate void DynamicTabItemCloseEvent(object sender, DynamicTabControlEventArgs args);
    
    public delegate void DynamicTabItemContextMenuEvent(object sender, DynamicTabItemContextMenuEventArgs args);

    public delegate void DynamicTabItemRenamedEvent(object sender, DynamicTabItemRenamedEventArgs args);
    
    public class DynamicTabControl : TabControl
    {

        public event DynamicTabControlChangedEvent OnTabsChanged;
        
        public static readonly DependencyProperty ChangedCommandProperty =
            DependencyProperty.Register(nameof(ChangedCommand), typeof(ICommand), typeof(DynamicTabControl));

        public ICommand ChangedCommand
        {
            get { return base.GetValue(ChangedCommandProperty) as ICommand; }
            set { base.SetValue(ChangedCommandProperty, value); }
        }
        
        public event DynamicTabControlCreateEvent OnCreateTab;
        
        public static readonly DependencyProperty CreateTabCommandProperty =
            DependencyProperty.Register(nameof(CreateTabCommand), typeof(ICommand), typeof(DynamicTabControl));

        public ICommand CreateTabCommand
        {
            get { return base.GetValue(CreateTabCommandProperty) as ICommand; }
            set { base.SetValue(CreateTabCommandProperty, value); }
        }

        public static readonly DependencyProperty CanCreateTabProperty =
            DependencyProperty.Register(nameof(CanCreateTab), typeof(bool), typeof(DynamicTabControl), new PropertyMetadata(false));
        
        public bool CanCreateTab
        {
            get => (bool)GetValue(CanCreateTabProperty);
            set => SetValue(CanCreateTabProperty, value);
        }
        
        public static readonly DependencyProperty LeftPanelProperty =
            DependencyProperty.Register(nameof(LeftPanel), typeof(FrameworkElement), typeof(DynamicTabControl), new UIPropertyMetadata(null));
        
        public FrameworkElement LeftPanel
        {
            get => (FrameworkElement)GetValue(LeftPanelProperty);
            set => SetValue(LeftPanelProperty, value);
        }
        
        public static readonly DependencyProperty RightPanelProperty =
            DependencyProperty.Register(nameof(RightPanel), typeof(FrameworkElement), typeof(DynamicTabControl), new UIPropertyMetadata(null));
        
        public FrameworkElement RightPanel
        {
            get => (FrameworkElement)GetValue(RightPanelProperty);
            set => SetValue(RightPanelProperty, value);
        }

        public DynamicTabItem? SelectedTab => (SelectedItem as DynamicTabItem)!;
        
        static DynamicTabControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicTabControl), new FrameworkPropertyMetadata(typeof(DynamicTabControl)));
        }

        public DynamicTabControl() : base()
        {

            ChangedCommand = new ActionCommand(() => OnTabsChanged?.Invoke(this, new EventArgs()));
            
            CanCreateTab = false;
            CreateTabCommand = new ActionCommand(() =>
            {
                var args = new DynamicTabControlEventArgs() { TabItem = new DynamicTabItem() { Header = "New TabItem" }};
                OnCreateTab?.Invoke(this, args);
                if (args.Cancel == false)
                {
                    Items.Add(args.TabItem);
                    ChangedCommand.Execute(null);
                }
            });
        }
        
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new DynamicTabItem();
        }

        public static readonly DependencyProperty TabStripVisibleProperty =
            DependencyProperty.Register(nameof(TabStripVisible), typeof(bool), typeof(DynamicTabControl), new PropertyMetadata(true));

        private double _tabStripHeight;
        public bool TabStripVisible
        {
            get => (bool)GetValue(TabStripVisibleProperty);
            set
            {
                SetValue(TabStripVisibleProperty, value);
                Style s = new Style();
                s.Setters.Add(new Setter(UIElement.VisibilityProperty, value ? Visibility.Visible : Visibility.Collapsed));
                ItemContainerStyle = s;

                if (!value)
                {
                    _tabStripHeight = TabStripHeight;
                    TabStripHeight = 0;
                }
                else if(TabStripHeight == 0)
                {
                    TabStripHeight = _tabStripHeight;
                }
            }
        }
        
        public static readonly DependencyProperty SeparatorMarginProperty =
            DependencyProperty.Register(nameof(SeparatorMargin), typeof(double), typeof(DynamicTabControl), new PropertyMetadata(1.5));
        
        public double SeparatorMargin
        {
            get => (double)GetValue(SeparatorMarginProperty);
            set => SetValue(SeparatorMarginProperty, value);
        }
        
        public static readonly DependencyProperty TabStripHeightProperty =
            DependencyProperty.Register(nameof(TabStripHeight), typeof(double), typeof(DynamicTabControl), new PropertyMetadata(25.0));
        
        public double TabStripHeight
        {
            get => (double)GetValue(TabStripHeightProperty);
            set => SetValue(TabStripHeightProperty, value);
        }
    }
}
