using System.Drawing;
using KioskApp.Portal.Platforms.Events;
using NWindows.Events;
using NWindows.Threading;

namespace KioskApp.Portal.Platforms.Windows;

public class WindowsWindow : Window
{
    public override event EventHandler<WindowClosingEventArgs> Closing;
    
    private NWindows.Window _nativeWindow;
    public WindowsWindow(WindowOptions options) : base(options)
    {
        InternalCreate();   
    }

    protected override bool Close()
    {
        var args = new WindowClosingEventArgs();
        Closing?.Invoke(this, args);
        if (args.Cancel) return false;
        
        _nativeWindow.Events.Frame -= EventsOnFrame;
        _nativeWindow.Events.Close -= EventsOnClose;
        
        // Dispose all widgets
        var widgets = GetWidgets();
        foreach (var widget in widgets)
        {
            widget.Dispose();
        }
        
        // TODO: We only need to call it when the last window is closed
        Dispatcher.Current.Shutdown();
        return true;
    }

    public override void Show()
    {
        _nativeWindow.Visible = true;
        _nativeWindow.Events.Frame += EventsOnFrame;
        _nativeWindow.Events.Close += EventsOnClose;
        Dispatcher.Current.Run();
    }

    public override T GetNativeWindow<T>()
    {
        return (_nativeWindow as T)!;
    }

    private void EventsOnClose(NWindows.Window window, CloseEvent evt)
    {
        evt.Cancel = !Close();
    }

    private void EventsOnFrame(NWindows.Window window, FrameEvent evt)
    {
        switch (evt.ChangeKind)
        {
            case FrameChangeKind.Resized:
            case FrameChangeKind.Maximized:
            case FrameChangeKind.Restored:
                InternalResize((int)_nativeWindow.Size.Width, (int)_nativeWindow.Size.Height);
                break;
            case FrameChangeKind.None:
                break;
            case FrameChangeKind.Created:
                break;
            case FrameChangeKind.Destroyed:
                break;
            case FrameChangeKind.PositionAndSizeChanged:
                break;
            case FrameChangeKind.Shown:
                break;
            case FrameChangeKind.Hidden:
                break;
            case FrameChangeKind.Moved:
                break;
            case FrameChangeKind.Minimized:
                break;
            case FrameChangeKind.FullScreen:
                break;
            case FrameChangeKind.FocusGained:
                break;
            case FrameChangeKind.FocusLost:
                break;
            case FrameChangeKind.MinimumSizeChanged:
                break;
            case FrameChangeKind.MaximumSizeChanged:
                break;
            case FrameChangeKind.ResizeableChanged:
                break;
            case FrameChangeKind.StateChanged:
                break;
            case FrameChangeKind.OpacityChanged:
                break;
            case FrameChangeKind.TopMostChanged:
                break;
            case FrameChangeKind.ModalChanged:
                break;
            case FrameChangeKind.Enabled:
                break;
            case FrameChangeKind.Disabled:
                break;
            case FrameChangeKind.TitleChanged:
                break;
            case FrameChangeKind.MaximizeableChanged:
                break;
            case FrameChangeKind.MinimizeableChanged:
                break;
            case FrameChangeKind.BackgroundColorChanged:
                break;
            case FrameChangeKind.ShowInTaskBarChanged:
                break;
            case FrameChangeKind.DpiChanged:
                break;
            case FrameChangeKind.DpiModeChanged:
                break;
            case FrameChangeKind.DragDropChanged:
                break;
            case FrameChangeKind.ClipboardChanged:
                break;
            case FrameChangeKind.DecorationsChanged:
                break;
            case FrameChangeKind.ThemeChanged:
                break;
            case FrameChangeKind.ThemeSyncModeChanged:
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

    public override IntPtr GetNativeHandle()
    {
        return _nativeWindow.Handle;
    }

    protected sealed override void InternalCreate()
    {
        _nativeWindow = NWindows.Window.Create(new()
        {
            Title = Title,
        });
        _nativeWindow.Size = new(Width, Height);
    }
    
    public sealed override SizeF GetClientSize()
    {
        Dispatcher.Current.VerifyAccess();
        return _nativeWindow.ClientSize;
    }

    public override void Fullscreen()
    {
        var screen = _nativeWindow.GetScreen();
        
        if(screen == null) return;
        
        _nativeWindow.Position = new(0, 0);
        _nativeWindow.Decorations = false;
        _nativeWindow.TopMost = true;
        _nativeWindow.Size = screen.Size;
    }

    protected override void InternalResize(int width, int height)
    {
        Width = width;
        Height = height;

        var clientSize = GetClientSize();
        
        var widgets = GetWidgets();
        foreach (var widget in widgets)
        {
            widget.Resize((int)clientSize.Width, (int)clientSize.Height);
        }
    }
}