using Godot;
using Mr.BrickAdventures.Autoloads;

namespace Mr.BrickAdventures.scripts.UI;

public partial class DisplaySettings : Control
{
    [Export] public OptionButton WindowModeButton { get; set; }
    [Export] public OptionButton ResolutionButton { get; set; }
    [Export] public Control DisplaySettingsControl { get; set; }

    private UIManager UIManager => UIManager.Instance;

    public override void _Ready()
    {
        PopulateWindowMode();
        PopulateResolutions();

        WindowModeButton.ItemSelected += OnWindowModeChanged;
        ResolutionButton.ItemSelected += OnResolutionChanged;

        WindowModeButton.FocusMode = Control.FocusModeEnum.All;
        ResolutionButton.FocusMode = Control.FocusModeEnum.All;

        LoadSettings();

        if (InputDeviceManager.Instance != null)
            InputDeviceManager.Instance.DeviceChanged += OnDeviceChanged;
        DisplaySettingsControl.VisibilityChanged += OnVisibilityChanged;
    }

    public override void _ExitTree()
    {
        if (InputDeviceManager.Instance != null)
            InputDeviceManager.Instance.DeviceChanged -= OnDeviceChanged;
        DisplaySettingsControl.VisibilityChanged -= OnVisibilityChanged;
        SettingsManager.Instance?.SaveDisplaySettings();
    }

    public override void _UnhandledInput(InputEvent @event)
    {
        if (!@event.IsActionReleased("ui_cancel")) return;
        if (!UIManager.IsScreenOnTop(DisplaySettingsControl)) return;

        SettingsManager.Instance?.SaveDisplaySettings();
        UIManager.PopScreen();
    }

    private void OnVisibilityChanged()
    {
        if (DisplaySettingsControl.IsVisibleInTree() && InputDeviceManager.Instance?.IsPointerless == true)
            GrabFirstFocus();
    }

    private void OnDeviceChanged(int device)
    {
        var d = (InputDeviceManager.InputDevice)device;
        if (d != InputDeviceManager.InputDevice.Mouse && DisplaySettingsControl.IsVisibleInTree())
            GrabFirstFocus();
    }

    private void GrabFirstFocus() => WindowModeButton.GrabFocus();

    private void PopulateWindowMode()
    {
        WindowModeButton.Clear();
        WindowModeButton.AddItem("Fullscreen", 0);
        WindowModeButton.AddItem("Borderless", 1);
        WindowModeButton.AddItem("Windowed", 2);
    }

    private void PopulateResolutions()
    {
        ResolutionButton.Clear();
        foreach (var res in SettingsManager.Instance.GetAllResolutions())
        {
            string label = $"{res.X}×{res.Y}";
            ResolutionButton.AddItem(label);
        }
    }

    private void OnWindowModeChanged(long idx)
    {
        string mode = idx switch
        {
            0 => "fullscreen",
            1 => "borderless",
            _ => "windowed"
        };

        SettingsManager.Instance.WindowMode = mode;
        SettingsManager.Instance.ApplyDisplaySettings();
        ResolutionButton.Disabled = mode == "fullscreen";
        SettingsManager.Instance.SaveDisplaySettings();
    }

    private void OnResolutionChanged(long idx)
    {
        var resolutions = SettingsManager.Instance.GetAllResolutions();
        if (idx < 0 || idx >= resolutions.Count) return;

        var res = resolutions[(int)idx];
        SettingsManager.Instance.Resolution = res;
        SettingsManager.Instance.ApplyDisplaySettings();
        SettingsManager.Instance.SaveDisplaySettings();
    }

    private void LoadSettings()
    {
        var mode = SettingsManager.Instance.WindowMode;
        WindowModeButton.Selected = mode switch
        {
            "fullscreen" => 0,
            "borderless" => 1,
            _ => 2
        };
        ResolutionButton.Disabled = mode == "fullscreen";

        var resolution = SettingsManager.Instance.Resolution;
        var resolutions = SettingsManager.Instance.GetAllResolutions();
        int resIdx = resolutions.IndexOf(resolution);
        if (resIdx >= 0)
            ResolutionButton.Selected = resIdx;
    }
}
