using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using HellionChat.Resources;
using HellionChat.Util;

namespace HellionChat.Ui.SettingsTabs;

internal sealed class General : ISettingsTab
{
    private Plugin Plugin { get; }
    private Configuration Mutable { get; }

    public string Name => HellionStrings.Settings_Tab_General + "###tabs-general";

    internal General(Plugin plugin, Configuration mutable)
    {
        Plugin = plugin;
        Mutable = mutable;
    }

    public void Draw(bool sectionJustEntered)
    {
        DrawInputSection(sectionJustEntered);
        ImGui.Spacing();
        DrawSoundSection(sectionJustEntered);
        ImGui.Spacing();
        DrawLanguageSection(sectionJustEntered);
        ImGui.Spacing();
        DrawPerformanceSection(sectionJustEntered);
    }

    private void DrawInputSection(bool sectionJustEntered)
    {
        // Collapse every time the tab is freshly entered so state doesn't bleed across sessions.
        if (sectionJustEntered)
            ImGui.SetNextItemOpen(false);
        using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Input);
        if (!tree.Success)
            return;

        using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
        {
            ImGui.Checkbox(Language.Options_KeepInputFocus_Name, ref Mutable.KeepInputFocus);
            ImGuiUtil.HelpMarker(Language.Options_KeepInputFocus_Description);

            ImGui.Spacing();
            ImGui.TextUnformatted(Language.Options_ChatTabForwardKeybind_Name);
            ImGui.SetNextItemWidth(-1);
            ImGuiUtil.KeybindInput("ChatTabForwardKeybind", ref Mutable.ChatTabForward);

            ImGui.TextUnformatted(Language.Options_ChatTabBackwardKeybind_Name);
            ImGui.SetNextItemWidth(-1);
            ImGuiUtil.KeybindInput("ChatTabBackwardKeybind", ref Mutable.ChatTabBackward);

            ImGui.Spacing();

            using (
                var combo = ImGuiUtil.BeginComboVertical(
                    Language.Options_KeybindMode_Name,
                    Mutable.KeybindMode.Name()
                )
            )
            {
                if (combo.Success)
                {
                    foreach (var mode in Enum.GetValues<KeybindMode>())
                    {
                        if (ImGui.Selectable(mode.Name(), Mutable.KeybindMode == mode))
                        {
                            Mutable.KeybindMode = mode;
                        }

                        if (ImGui.IsItemHovered())
                        {
                            ImGuiUtil.Tooltip(mode.Tooltip() ?? "");
                        }
                    }
                }
            }
            ImGuiUtil.HelpMarker(
                string.Format(Language.Options_KeybindMode_Description, Plugin.PluginName)
            );
        }
    }

    private void DrawSoundSection(bool sectionJustEntered)
    {
        // Collapse every time the tab is freshly entered so state doesn't bleed across sessions.
        if (sectionJustEntered)
            ImGui.SetNextItemOpen(false);
        using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Sound);
        if (!tree.Success)
            return;

        using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
        {
            ImGui.Checkbox(Language.Options_PlaySounds_Name, ref Mutable.PlaySounds);
            ImGuiUtil.HelpMarker(Language.Options_PlaySounds_Description);
            // Volume is stored as a 0-1 float but shown as 0-100% to match user
            // intuition. Full range — unlike opacity there is no unsafe floor.
            var customSoundVolumePercent = Mutable.CustomSoundVolume * 100f;
            if (
                ImGuiUtil.DragFloatVertical(
                    HellionStrings.Settings_General_CustomSoundVolume_Name,
                    ref customSoundVolumePercent,
                    1f,
                    0f,
                    100f,
                    $"{customSoundVolumePercent:N0}%%",
                    ImGuiSliderFlags.AlwaysClamp
                )
            )
            {
                Mutable.CustomSoundVolume = customSoundVolumePercent / 100f;
            }
            // Show the functional description and the per-tab navigation hint together.
            ImGuiUtil.HelpMarker(
                HellionStrings.Settings_General_CustomSoundVolume_Description
                    + "\n\n"
                    + HellionStrings.Settings_Section_Sound_TabsHint
            );
        }
    }

    private void DrawLanguageSection(bool sectionJustEntered)
    {
        // Collapse every time the tab is freshly entered so state doesn't bleed across sessions.
        if (sectionJustEntered)
            ImGui.SetNextItemOpen(false);
        using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Language);
        if (!tree.Success)
            return;

        using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
        {
            ImGui.Checkbox(Language.Options_SortAutoTranslate_Name, ref Mutable.SortAutoTranslate);
            ImGuiUtil.HelpMarker(Language.Options_SortAutoTranslate_Description);

            ImGui.Spacing();

            using (
                var combo = ImGuiUtil.BeginComboVertical(
                    Language.Options_Language_Name,
                    Mutable.LanguageOverride.Name()
                )
            )
            {
                if (combo.Success)
                {
                    // None pinned first, then alphabetical by endonym so source order
                    // (append-only for serialisation safety) is not visible to users.
                    var sortedLanguages = Enum.GetValues<LanguageOverride>()
                        .OrderBy(l => l == LanguageOverride.None ? 0 : 1)
                        .ThenBy(l => l.Name(), StringComparer.InvariantCulture);
                    foreach (var language in sortedLanguages)
                    {
                        if (ImGui.Selectable(language.Name()))
                        {
                            Mutable.LanguageOverride = language;
                        }
                    }
                }
            }
            ImGuiUtil.HelpMarker(
                string.Format(Language.Options_Language_Description, Plugin.PluginName)
            );
            // v1.5.3: HellionChat's font stack covers 24 languages but FFXIV's
            // engine only supports EN/DE/FR/JA for chat input/sending.
            ImGuiUtil.WarningText(HellionStrings.Settings_Language_FFXIVCoverage_Warning);
            ImGui.Spacing();

            using (
                var combo = ImGuiUtil.BeginComboVertical(
                    Language.Options_CommandHelpSide_Name,
                    Mutable.CommandHelpSide.Name()
                )
            )
            {
                if (combo.Success)
                {
                    foreach (var side in Enum.GetValues<CommandHelpSide>())
                    {
                        if (ImGui.Selectable(side.Name(), Mutable.CommandHelpSide == side))
                        {
                            Mutable.CommandHelpSide = side;
                        }
                    }
                }
            }
            ImGuiUtil.HelpMarker(
                string.Format(Language.Options_CommandHelpSide_Description, Plugin.PluginName)
            );
            ImGui.Spacing();
        }
    }

    private void DrawPerformanceSection(bool sectionJustEntered)
    {
        // Collapse every time the tab is freshly entered so state doesn't bleed across sessions.
        if (sectionJustEntered)
            ImGui.SetNextItemOpen(false);
        using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Performance);
        if (!tree.Success)
            return;

        using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
        {
            ImGui.SetNextItemWidth(200f * ImGuiHelpers.GlobalScale);
            if (ImGui.InputInt(Language.Options_MaxLinesToShow_Name, ref Mutable.MaxLinesToRender))
            {
                Mutable.MaxLinesToRender = Math.Clamp(Mutable.MaxLinesToRender, 1, 10_000);
            }
            ImGuiUtil.HelpMarker(Language.Options_MaxLinesToShow_Description);
        }
    }
}
