using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using InABox.Core;
using Syncfusion.Windows.Controls.Input;

namespace InABox.DynamicGrid;

[Flags]
public enum DynamicSplitPanelView
{
    Master = 1,
    Detail = 2,
    Combined = 4
}

public enum DynamicSplitPanelAnchor
{
    Master,
    Detail
}

public class DynamicSplitPanelSettings : EventArgs
{
    public DynamicSplitPanelView View { get; set; }
    public double AnchorWidth { get; set; }
    public double DetailHeight { get; set; }
}

public delegate void DynamicSplitPanelChanged(object sender, DynamicSplitPanelSettings e);

public class DynamicSplitPanel : Control
{
    
    public static readonly DependencyProperty AllowableViewsProperty = DependencyProperty.Register(
        nameof(AllowableViews), 
        typeof(DynamicSplitPanelView),
        typeof(DynamicSplitPanel), 
        new UIPropertyMetadata( DynamicSplitPanelView.Master | DynamicSplitPanelView.Combined | DynamicSplitPanelView.Detail ));
    
    public static readonly DependencyProperty ViewProperty = DependencyProperty.Register("View", typeof(DynamicSplitPanelView),
        typeof(DynamicSplitPanel), new UIPropertyMetadata(DynamicSplitPanelView.Detail));

    public static readonly DependencyProperty AnchorProperty = DependencyProperty.Register(nameof(Anchor), typeof(DynamicSplitPanelAnchor),
        typeof(DynamicSplitPanel), new UIPropertyMetadata(DynamicSplitPanelAnchor.Master));
    
    public static readonly DependencyProperty AnchorWidthProperty =
        DependencyProperty.Register(nameof(AnchorWidth), typeof(double), typeof(DynamicSplitPanel), new UIPropertyMetadata((double)300F));

    public static readonly DependencyProperty MasterCaptionProperty =
        DependencyProperty.Register("MasterCaption", typeof(string), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty DetailCaptionProperty =
        DependencyProperty.Register("DetailCaption", typeof(string), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty MasterProperty =
        DependencyProperty.Register(nameof(Master), typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty DetailHeaderProperty =
        DependencyProperty.Register("DetailHeader", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty DetailProperty =
        DependencyProperty.Register("Detail", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    public static readonly DependencyProperty DetailHeightProperty =
        DependencyProperty.Register("DetailHeight", typeof(double), typeof(DynamicSplitPanel), new UIPropertyMetadata((double)200F));

    public static readonly DependencyProperty SecondaryDetailProperty = DependencyProperty.Register("SecondaryDetail", typeof(FrameworkElement),
        typeof(DynamicSplitPanel), new UIPropertyMetadata(null));

    private Button CombinedLeft;
    private Button CombinedRight;

    private Grid DetailGrid;
    private Label DetailsHeader;
    private Button DetailsOnly;
    private SfGridSplitter DetailSplitter;

    private Grid Grid;
    private Label MasterHeader;
    private Button MasterOnly;
    private SfGridSplitter Splitter;


    static DynamicSplitPanel()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicSplitPanel), new FrameworkPropertyMetadata(typeof(DynamicSplitPanel)));
    }
    
    public DynamicSplitPanelView AllowableViews
    {
        get => (DynamicSplitPanelView)GetValue(AllowableViewsProperty);
        set
        {
            SetValue(AllowableViewsProperty, value);
            ConfigureScreen();
        }
        
    }    
    
    private bool IsViewAllowed(params DynamicSplitPanelView[] views)
    {
        foreach (var view in views)
        {
            if ((AllowableViews & view) == view)
                return true;
        }
        return false;
    }

    public DynamicSplitPanelView View
    {
        get => (DynamicSplitPanelView)GetValue(ViewProperty);
        set
        {
            SetValue(ViewProperty, value);
            ConfigureScreen();
        }
    }

    public DynamicSplitPanelAnchor Anchor
    {
        get => (DynamicSplitPanelAnchor)GetValue(AnchorProperty);
        set 
        {
            SetValue(AnchorProperty, value);
            ConfigureScreen();
        }
    }
    
    public double AnchorWidth
    {
        get => (double)GetValue(AnchorWidthProperty);
        set
        {
            SetValue(AnchorWidthProperty, value);
            ConfigureScreen();
        }
    }

    public string MasterCaption
    {
        get => (string)GetValue(MasterCaptionProperty);
        set => SetValue(MasterCaptionProperty, value);
        //MasterHeader.Content = value;
    }

    public string DetailCaption
    {
        get => (string)GetValue(DetailCaptionProperty);
        set => SetValue(DetailCaptionProperty, value);
        //DetailHeader.Content = value;
    }

    public FrameworkElement Header
    {
        get => (FrameworkElement)GetValue(HeaderProperty);
        set => SetValue(HeaderProperty, value);
    }

    public FrameworkElement Master
    {
        get => (FrameworkElement)GetValue(MasterProperty);
        set => SetValue(MasterProperty, value);
    }

    public FrameworkElement DetailHeader
    {
        get => (FrameworkElement)GetValue(DetailHeaderProperty);
        set => SetValue(DetailHeaderProperty, value);
    }

    public FrameworkElement Detail
    {
        get => (FrameworkElement)GetValue(DetailProperty);
        set => SetValue(DetailProperty, value);
    }

    public double DetailHeight
    {
        get => (double)GetValue(DetailHeightProperty);
        set
        {
            SetValue(DetailHeightProperty, value);
            ConfigureScreen();
        }
    }

    public FrameworkElement SecondaryDetail
    {
        get => (FrameworkElement)GetValue(SecondaryDetailProperty);
        set => SetValue(SecondaryDetailProperty, value);
    }

    public event DynamicSplitPanelChanged OnChanged;

    private void RightClick(object sender, RoutedEventArgs e)
    {
        if (View == DynamicSplitPanelView.Detail)
            View = DynamicSplitPanelView.Combined;
        else if (View == DynamicSplitPanelView.Combined)
            View = DynamicSplitPanelView.Master;
        Changed();
    }

    private void LeftClick(object sender, RoutedEventArgs e)
    {
        if (View == DynamicSplitPanelView.Master)
            View = DynamicSplitPanelView.Combined;
        else if (View == DynamicSplitPanelView.Combined)
            View = DynamicSplitPanelView.Detail;
        Changed();
    }

    public bool IsMasterVisible() => View == DynamicSplitPanelView.Master || View == DynamicSplitPanelView.Combined;

    public bool IsDetailVisible() => View == DynamicSplitPanelView.Detail || View == DynamicSplitPanelView.Combined;

    private void ConfigureScreen()
    {
        CheckParts();
        try
        {
            if (MasterHeader != null)
                MasterHeader.Content = MasterCaption;
            
            if (DetailsHeader != null)
                DetailsHeader.Content = DetailCaption;

            if (CombinedLeft != null)
                CombinedLeft.Visibility = View == DynamicSplitPanelView.Combined && AllowableViews.HasFlag(DynamicSplitPanelView.Master) ? Visibility.Visible : Visibility.Collapsed;

            if (CombinedRight != null)
                CombinedRight.Visibility = View == DynamicSplitPanelView.Combined && AllowableViews.HasFlag(DynamicSplitPanelView.Detail) ? Visibility.Visible : Visibility.Collapsed;

            if (Grid != null)
            {
                Grid.ColumnDefinitions[0].Width = (View == DynamicSplitPanelView.Detail) 
                                                  && (Master != null) 
                                                  && (IsViewAllowed(DynamicSplitPanelView.Combined,DynamicSplitPanelView.Master))
                    ? new GridLength(1.0F, GridUnitType.Auto)
                    : new GridLength(0.0F, GridUnitType.Pixel);
                
                Grid.ColumnDefinitions[1].Width = Master == null 
                    ? new GridLength(0.0F, GridUnitType.Pixel) 
                    : View switch { 
                        DynamicSplitPanelView.Master => new GridLength(1.0F, GridUnitType.Star),
                        DynamicSplitPanelView.Detail => new GridLength(0.0F, GridUnitType.Pixel),
                        _ => Anchor == DynamicSplitPanelAnchor.Master 
                            ? new GridLength(AnchorWidth, GridUnitType.Pixel) 
                            : new GridLength(1.0F, GridUnitType.Star)
                    };
                
                Grid.ColumnDefinitions[2].Width = (View == DynamicSplitPanelView.Combined) 
                                                  && (Master != null)
                    ? new GridLength(1.0F, GridUnitType.Auto)
                    : new GridLength(0.0F, GridUnitType.Pixel);

                Grid.ColumnDefinitions[3].Width = View switch
                {
                    DynamicSplitPanelView.Master => new GridLength(0.0F, GridUnitType.Pixel),
                    DynamicSplitPanelView.Detail => new GridLength(1.0F, GridUnitType.Star),
                    _ => Anchor == DynamicSplitPanelAnchor.Detail
                        ? new GridLength(AnchorWidth, GridUnitType.Pixel)
                        : new GridLength(1.0F, GridUnitType.Star)
                };
                    
                Grid.ColumnDefinitions[4].Width = (View == DynamicSplitPanelView.Master) 
                                                  && (IsViewAllowed(DynamicSplitPanelView.Combined,DynamicSplitPanelView.Detail))
                    ? new GridLength(1.0F, GridUnitType.Auto)
                    : new GridLength(0.0F, GridUnitType.Pixel);
                
                Grid.RowDefinitions[0].Height =
                    Header == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Auto);
            }

            if (DetailGrid != null)
            {
                DetailGrid.SetValue(Grid.RowProperty, DetailHeader == null ? 0 : 1);
                DetailGrid.SetValue(Grid.RowSpanProperty, DetailHeader == null ? 2 : 1);
                DetailGrid.RowDefinitions[0].Height = SecondaryDetail == null
                    ? new GridLength(1.0F, GridUnitType.Star)
                    : new GridLength(DetailHeight, GridUnitType.Pixel);
                DetailGrid.RowDefinitions[1].Height =
                    SecondaryDetail == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Auto);
                DetailGrid.RowDefinitions[2].Height =
                    SecondaryDetail == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Star);
                DetailSplitter.IsEnabled = SecondaryDetail != null;
            }


            if (CombinedRight != null)
            {
                CombinedRight.Visibility = (View == DynamicSplitPanelView.Combined) && IsViewAllowed(DynamicSplitPanelView.Master)
                    ? Visibility.Visible
                    : Visibility.Collapsed;
            }
            
            if (CombinedLeft != null)
            {
                CombinedLeft.Visibility = (View == DynamicSplitPanelView.Combined) && IsViewAllowed(DynamicSplitPanelView.Detail)
                    ? Visibility.Visible
                    : Visibility.Collapsed;
            }

        }
        catch (Exception e)
        {
            Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
        }
    }

    private void Splitter_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (Anchor == DynamicSplitPanelAnchor.Master)
            SetValue(AnchorWidthProperty, Grid.ColumnDefinitions[1].ActualWidth);
        else 
            SetValue(AnchorWidthProperty, Grid.ColumnDefinitions[3].ActualWidth);
        SetValue(DetailHeightProperty, SecondaryDetail == null ? 0.0F : DetailGrid.RowDefinitions[0].ActualHeight);
        Changed();
    }

    private void Changed()
    {
        OnChanged?.Invoke(this, new DynamicSplitPanelSettings { View = View, AnchorWidth = AnchorWidth, DetailHeight = DetailHeight });
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        CheckParts();

        ConfigureScreen();
    }

    private void CheckParts()
    {
        try
        {
            if (Grid == null)
                Grid = GetTemplateChild("PART_Grid") as Grid;

            if (DetailGrid == null)
                DetailGrid = GetTemplateChild("PART_DetailGrid") as Grid;

            if (MasterHeader == null)
                MasterHeader = GetTemplateChild("PART_MasterHeader") as Label;

            if (DetailsHeader == null)
                DetailsHeader = GetTemplateChild("PART_DetailHeader") as Label;

            if (Splitter == null)
            {
                Splitter = GetTemplateChild("PART_Splitter") as SfGridSplitter;
                if (Splitter != null)
                {
                    Splitter.PreviewMouseUp += Splitter_PreviewMouseUp;
                    Splitter.TargetUpdated += Splitter_TargetUpdated;
                }
            }

            if (DetailSplitter == null)
            {
                DetailSplitter = GetTemplateChild("PART_DetailSplitter") as SfGridSplitter;
                if (DetailSplitter != null)
                    DetailSplitter.PreviewMouseUp += Splitter_PreviewMouseUp;
            }

            if (DetailsOnly == null)
            {
                DetailsOnly = GetTemplateChild("PART_DetailsOnly") as Button;
                if (DetailsOnly != null)
                    DetailsOnly.Click += RightClick;
            }

            if (CombinedRight == null)
            {
                CombinedRight = GetTemplateChild("PART_CombinedRight") as Button;
                if (CombinedRight != null)
                    CombinedRight.Click += RightClick;
            }

            if (CombinedLeft == null)
            {
                CombinedLeft = GetTemplateChild("PART_CombinedLeft") as Button;
                if (CombinedLeft != null)
                    CombinedLeft.Click += LeftClick;
            }

            if (MasterOnly == null)
            {
                MasterOnly = GetTemplateChild("PART_MasterOnly") as Button;
                if (MasterOnly != null)
                    MasterOnly.Click += LeftClick;
            }
        }
        catch (Exception e)
        {
            Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace));
        }
    }

    private void Splitter_TargetUpdated(object sender, DataTransferEventArgs e)
    {
        //
    }
}