using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using ICSharpCode.AvalonEdit;
using InABox.Configuration;
using InABox.Core;

namespace InABox.Wpf;

public interface IPanelActionItem
{

}

public class PanelAction : DependencyObject, IPanelActionItem
{
    public Action<PanelAction>? OnExecute { get; set; }
    
    public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(
        nameof(IsEnabled),
        typeof(bool),
        typeof(PanelAction),
        new PropertyMetadata(true)
    );
    
    public bool IsEnabled 
    { 
        get => (bool)GetValue(IsEnabledProperty);
        set => SetValue(IsEnabledProperty, value);
    }
    public static readonly DependencyProperty VisibilityProperty = DependencyProperty.Register(
        nameof(Visibility),
        typeof(Visibility),
        typeof(PanelAction),
        new PropertyMetadata(Visibility.Visible)
    );
    
    public Visibility Visibility 
    { 
        get => (Visibility)GetValue(VisibilityProperty);
        set => SetValue(VisibilityProperty, value);
    }

    public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register(
        nameof(Caption),
        typeof(string),
        typeof(PanelAction),
        new PropertyMetadata("")
    );
    
    public string Caption 
    { 
        get => (string)GetValue(CaptionProperty);
        set => SetValue(CaptionProperty, value);
    }

    public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(
        nameof(Image),
        typeof(Bitmap),
        typeof(PanelAction)
    );    
    public Bitmap? Image
    { 
        get => GetValue(ImageProperty) as Bitmap;
        set => SetValue(ImageProperty, value);
    }
    
    public static readonly DependencyProperty MenuProperty = DependencyProperty.Register(
        nameof(Menu),
        typeof(ContextMenu),
        typeof(PanelAction)
    );   
    
    public ContextMenu? Menu
    { 
        get => GetValue(MenuProperty) as ContextMenu;
        set => SetValue(MenuProperty, value);
    }

    public PanelAction()
    {
    }
    public PanelAction(string caption, Bitmap image, Action<PanelAction> onExecute, ContextMenu? menu = null)
    {
        Caption = caption;
        Image = image;
        Menu = menu;
        OnExecute = onExecute;
    }

    public void Execute()
    {
        OnExecute?.Invoke(this);
    }
}
public class PanelActionSeparator : IPanelActionItem
{

}

public interface ICorePanel
{
    void Setup();

    /// <summary>
    /// Shutdown the panel.
    /// </summary>
    /// <param name="cancel">If the operation can be cancelled, this is not <see langword="null"/></param>
    void Shutdown(CancelEventArgs? cancel);

    void Refresh();
}

public interface IBasePanel : ICorePanel, IDataModelSource
{
    bool IsReady { get; set; }
    void CreateToolbarButtons(IPanelHost host);

    Dictionary<string, object[]> Selected();

    void Heartbeat(TimeSpan time);
}

public interface IPanel<T> : IBasePanel
{
}

public interface IPropertiesPanel<TProperties>
    where TProperties : BaseObject, IGlobalConfigurationSettings, new()
{
    public TProperties Properties { get; set; }
}

public interface IPropertiesPanel<TProperties, TSecurity> : IPropertiesPanel<TProperties>
    where TProperties : BaseObject, IGlobalConfigurationSettings, new()
    where TSecurity : ISecurityDescriptor, new()
{
}

public interface IPanelHost
{
    void CreatePanelAction(PanelAction action);

    void CreateReport(PanelAction action);

    void CreateSetupAction(PanelAction action);

    void CreateSetupSeparator();
}

public static class IPanelHostExtensions
{
    public static void CreateSetupAction(this IPanelHost host, string caption, Bitmap image, Action<PanelAction> onExecute, ContextMenu? menu = null)
    {
        host.CreateSetupAction(new PanelAction(caption, image, onExecute, menu));
    }

    public static void CreateSetupActionIf(this IPanelHost host, string caption, Bitmap image, Action<PanelAction> onExecute, bool canView, ContextMenu? menu = null)
    {
        if (canView)
        {
            host.CreateSetupAction(new PanelAction(caption, image, onExecute, menu));
        }
    }

    public static void CreateSetupActionIf<TSecurity>(this IPanelHost host, string caption, Bitmap image, Action<PanelAction> onExecute, ContextMenu? menu = null)
        where TSecurity : ISecurityDescriptor, new()
    {
        host.CreateSetupActionIf(caption, image, onExecute, Security.IsAllowed<TSecurity>(), menu);
    }

    public static void CreateSetupActionIfCanView<T>(this IPanelHost host, string caption, Bitmap image, Action<PanelAction> onExecute, ContextMenu? menu = null)
        where T : Entity, new()
    {
        host.CreateSetupActionIf(caption, image, onExecute, Security.CanView<T>(), menu);
    }
}