using ImGuiNET;
using Nerfed.Runtime.Graphics;
using System.Runtime.InteropServices;

namespace Nerfed.Runtime.Gui
{
    internal class GuiViewportWindow
    {
        public Window Window => window;

        private readonly GCHandle gcHandle;
        private readonly GraphicsDevice graphicsDevice;
        private readonly ImGuiViewportPtr vp;
        private readonly Window window;

        public GuiViewportWindow(GraphicsDevice graphicsDevice, ImGuiViewportPtr vp, Window window)
        {
            this.graphicsDevice = graphicsDevice;
            this.vp = vp;
            this.window = window;

            gcHandle = GCHandle.Alloc(this);

            if (!window.Claimed)
            {
                graphicsDevice.ClaimWindow(window, SwapchainComposition.SDR, PresentMode.Immediate); // What PresentMode do we need?
            }

            vp.PlatformUserData = (IntPtr)gcHandle;
        }

        public GuiViewportWindow(GraphicsDevice graphicsDevice, ImGuiViewportPtr vp)
        {
            this.graphicsDevice = graphicsDevice;
            this.vp = vp;

            gcHandle = GCHandle.Alloc(this);

            // TODO: Handle all flags.
            ScreenMode screenMode = ScreenMode.Windowed;
            bool systemResizable = true;

            if ((vp.Flags & ImGuiViewportFlags.NoDecoration) == ImGuiViewportFlags.NoDecoration)
            {
                screenMode = ScreenMode.WindowedBorderless;
                systemResizable = false;
            }

            WindowCreateInfo info = new WindowCreateInfo("Window Title", (uint)vp.Pos.X, (uint)vp.Pos.Y, screenMode, systemResizable, false);

            window = new Window(graphicsDevice, info);
            graphicsDevice.ClaimWindow(window, SwapchainComposition.SDR, PresentMode.Immediate); // What PresentMode do we need?

            window.OnMovedEvent += HandleOnMovedEvent;
            window.OnResizedEvent += HandleOnResizedEvent;
            window.OnCloseEvent += HandleOnCloseEvent;

            vp.PlatformUserData = (IntPtr)gcHandle;
        }

        public void Dispose()
        {
            window.OnMovedEvent -= HandleOnMovedEvent;
            window.OnResizedEvent -= HandleOnResizedEvent;
            window.OnCloseEvent -= HandleOnCloseEvent;

            graphicsDevice.UnclaimWindow(window);
            window.Dispose();
            gcHandle.Free();
        }

        private void HandleOnMovedEvent(Window window, int x, int y)
        {
            vp.PlatformRequestMove = true;
        }

        private void HandleOnResizedEvent(Window window, uint w, uint h)
        {
            vp.PlatformRequestResize = true;
        }

        private void HandleOnCloseEvent(Window window)
        {
            vp.PlatformRequestClose = true;
        }
    }
}