using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii;
using LightlessSync.API.Data.Enum;
using LightlessSync.API.Data.Extensions;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI.Handlers;
using LightlessSync.UI.Models;
using LightlessSync.WebAPI;

namespace LightlessSync.UI.Components;

public class DrawFolderTag : DrawFolderBase
{
    private readonly ApiController _apiController;
    private readonly SelectPairForTagUi _selectPairForTagUi;
    private readonly RenamePairTagUi _renameTagUi;
    private readonly ServerConfigurationManager _serverConfigurationManager;
    private readonly LightlessConfigService _configService;
    private readonly LightlessMediator _mediator;

    public DrawFolderTag(
        string id,
        IImmutableList<DrawUserPair> drawPairs,
        IImmutableList<PairUiEntry> allPairs,
        TagHandler tagHandler,
        ApiController apiController,
        SelectPairForTagUi selectPairForTagUi,
        RenamePairTagUi renameTagUi,
        UiSharedService uiSharedService,
        ServerConfigurationManager serverConfigurationManager,
        LightlessConfigService configService,
        LightlessMediator mediator)
        : base(id, drawPairs, allPairs, tagHandler, uiSharedService)
    {
        _apiController = apiController;
        _selectPairForTagUi = selectPairForTagUi;
        _renameTagUi = renameTagUi;
        _serverConfigurationManager = serverConfigurationManager;
        _configService = configService;
        _mediator = mediator;
    }

    protected override bool RenderIfEmpty => _id switch
    {
        TagHandler.CustomUnpairedTag => false,
        TagHandler.CustomOnlineTag => false,
        TagHandler.CustomOfflineTag => false,
        TagHandler.CustomVisibleTag => false,
        TagHandler.CustomAllTag => true,
        TagHandler.CustomOfflineSyncshellTag => false,
        _ => true,
    };

    protected override bool RenderMenu => _id switch
    {
        TagHandler.CustomUnpairedTag => false,
        TagHandler.CustomOnlineTag => false,
        TagHandler.CustomOfflineTag => false,
        TagHandler.CustomVisibleTag => false,
        TagHandler.CustomAllTag => false,
        TagHandler.CustomOfflineSyncshellTag => false,
        _ => true,
    };

    private bool RenderPause => _id switch
    {
        TagHandler.CustomUnpairedTag => false,
        TagHandler.CustomOnlineTag => false,
        TagHandler.CustomOfflineTag => false,
        TagHandler.CustomVisibleTag => false,
        TagHandler.CustomAllTag => false,
        TagHandler.CustomOfflineSyncshellTag => false,
        _ => true,
    } && _allPairs.Any();

    private bool RenderCount => _id switch
    {
        TagHandler.CustomUnpairedTag => false,
        TagHandler.CustomOnlineTag => false,
        TagHandler.CustomOfflineTag => false,
        TagHandler.CustomVisibleTag => false,
        TagHandler.CustomAllTag => false,
        TagHandler.CustomOfflineSyncshellTag => false,
        _ => true
    };

    protected override float DrawIcon()
    {
        var icon = _id switch
        {
            TagHandler.CustomUnpairedTag => FontAwesomeIcon.ArrowsLeftRight,
            TagHandler.CustomOnlineTag => FontAwesomeIcon.Link,
            TagHandler.CustomOfflineTag => FontAwesomeIcon.Unlink,
            TagHandler.CustomOfflineSyncshellTag => FontAwesomeIcon.Unlink,
            TagHandler.CustomVisibleTag => FontAwesomeIcon.Eye,
            TagHandler.CustomAllTag => FontAwesomeIcon.User,
            _ => FontAwesomeIcon.Folder
        };

        ImGui.AlignTextToFramePadding();
        _uiSharedService.IconText(icon);

        if (RenderCount)
        {
            using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
                       ImGui.GetStyle().ItemSpacing with { X = ImGui.GetStyle().ItemSpacing.X / 2f }))
            {
                ImGui.SameLine();
                ImGui.AlignTextToFramePadding();

                ImGui.TextUnformatted($"[{OnlinePairs}]");
            }

            UiSharedService.AttachToolTip($"{OnlinePairs} online{Environment.NewLine}{TotalPairs} total");
        }

        ImGui.SameLine();
        return ImGui.GetCursorPosX();
    }

    protected override void DrawMenu(float menuWidth)
    {
        ImGui.TextUnformatted("Group Menu");
        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Users, "Select Pairs", menuWidth, true))
        {
            _selectPairForTagUi.Open(_id);
        }

        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Edit, "Rename Pair Group", menuWidth, true))
        {
            _renameTagUi.Open(_id);
        }

        if (_uiSharedService.IconTextButton(FontAwesomeIcon.Trash, "Delete Pair Group", menuWidth, true) &&
            UiSharedService.CtrlPressed())
        {
            _tagHandler.RemovePairTag(_id);
        }

        UiSharedService.AttachToolTip(
            "Hold CTRL to remove this Group permanently." + Environment.NewLine +
            "Note: this will not unpair with users in this Group.");
    }

    protected override void DrawName(float width)
    {
        ImGui.AlignTextToFramePadding();

        var name = _id switch
        {
            TagHandler.CustomUnpairedTag => "One-sided Individual Pairs",
            TagHandler.CustomOnlineTag => "Online / Paused by you",
            TagHandler.CustomOfflineTag => "Offline / Paused by other",
            TagHandler.CustomOfflineSyncshellTag => "Offline Syncshell Users",
            TagHandler.CustomVisibleTag => "Visible",
            TagHandler.CustomAllTag => "Users",
            _ => _id
        };

        ImGui.TextUnformatted(name);
    }

    protected override float DrawRightSide(float currentRightSideX)
    {
        if (string.Equals(_id, TagHandler.CustomVisibleTag, StringComparison.Ordinal))
        {
            return DrawVisibleFilter(currentRightSideX);
        }

        if (string.Equals(_id, TagHandler.CustomOnlineTag, StringComparison.Ordinal))
        {
            return DrawOnlineFilter(currentRightSideX);
        }

        if (!RenderPause)
        {
            return currentRightSideX;
        }

        var allArePaused = _allPairs.All(entry => entry.SelfPermissions.IsPaused());
        var pauseIcon = allArePaused ? FontAwesomeIcon.Play : FontAwesomeIcon.Pause;
        var pauseButtonSize = _uiSharedService.GetIconButtonSize(pauseIcon);

        var buttonPauseOffset = currentRightSideX - pauseButtonSize.X;
        ImGui.SameLine(buttonPauseOffset);
        if (_uiSharedService.IconButton(pauseIcon))
        {
            SuppressNextRowToggle();
            if (allArePaused)
            {
                ResumeAllPairs(_allPairs);
            }
            else
            {
                PauseRemainingPairs(_allPairs);
            }
        }

        UiSharedService.AttachToolTip(allArePaused
            ? $"Resume pairing with all pairs in {_id}"
            : $"Pause pairing with all pairs in {_id}");

        return currentRightSideX;
    }

    private void PauseRemainingPairs(IEnumerable<PairUiEntry> entries)
    {
        _ = _apiController.SetBulkPermissions(new(
                entries.ToDictionary(entry => entry.DisplayEntry.User.UID, entry =>
                {
                    var permissions = entry.SelfPermissions;
                    permissions.SetPaused(true);
                    return permissions;
                }, StringComparer.Ordinal),
                new(StringComparer.Ordinal)))
            .ConfigureAwait(false);
    }

    private void ResumeAllPairs(IEnumerable<PairUiEntry> entries)
    {
        _ = _apiController.SetBulkPermissions(new(
                entries.ToDictionary(entry => entry.DisplayEntry.User.UID, entry =>
                {
                    var permissions = entry.SelfPermissions;
                    permissions.SetPaused(false);
                    return permissions;
                }, StringComparer.Ordinal),
                new(StringComparer.Ordinal)))
            .ConfigureAwait(false);
    }

    private float DrawVisibleFilter(float currentRightSideX)
    {
        var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Filter);
        var spacingX = ImGui.GetStyle().ItemSpacing.X;
        var buttonStart = currentRightSideX - buttonSize.X;

        ImGui.SameLine(buttonStart);
        if (_uiSharedService.IconButton(FontAwesomeIcon.Filter))
        {
            SuppressNextRowToggle();
            ImGui.OpenPopup($"visible-filter-{_id}");
        }

        UiSharedService.AttachToolTip("Adjust how visible pairs are ordered.");

        if (ImGui.BeginPopup($"visible-filter-{_id}"))
        {
            ImGui.TextUnformatted("Visible Pair Ordering");
            ImGui.Separator();

            foreach (VisiblePairSortMode mode in Enum.GetValues<VisiblePairSortMode>())
            {
                var selected = _configService.Current.VisiblePairSortMode == mode;
                if (ImGui.MenuItem(GetSortVisibleLabel(mode), string.Empty, selected))
                {
                    if (!selected)
                    {
                        _configService.Current.VisiblePairSortMode = mode;
                        _configService.Save();
                        _mediator.Publish(new RefreshUiMessage());
                    }

                    ImGui.CloseCurrentPopup();
                }
            }

            ImGui.EndPopup();
        }

        return buttonStart - spacingX;
    }

    private float DrawOnlineFilter(float currentRightSideX)
    {
        var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Filter);
        var spacingX = ImGui.GetStyle().ItemSpacing.X;
        var buttonStart = currentRightSideX - buttonSize.X;

        ImGui.SameLine(buttonStart);
        if (_uiSharedService.IconButton(FontAwesomeIcon.Filter))
        {
            SuppressNextRowToggle();
            ImGui.OpenPopup($"online-filter-{_id}");
        }

        UiSharedService.AttachToolTip("Adjust how online pairs are ordered.");

        if (ImGui.BeginPopup($"online-filter-{_id}"))
        {
            ImGui.TextUnformatted("Online Pair Ordering");
            ImGui.Separator();

            foreach (OnlinePairSortMode mode in Enum.GetValues<OnlinePairSortMode>())
            {
                var selected = _configService.Current.OnlinePairSortMode == mode;
                if (ImGui.MenuItem(GetSortOnlineLabel(mode), string.Empty, selected))
                {
                    if (!selected)
                    {
                        _configService.Current.OnlinePairSortMode = mode;
                        _configService.Save();
                        _mediator.Publish(new RefreshUiMessage());
                    }

                    ImGui.CloseCurrentPopup();
                }
            }

            ImGui.EndPopup();
        }

        return buttonStart - spacingX;
    }

    private static string GetSortVisibleLabel(VisiblePairSortMode mode) => mode switch
    {
        VisiblePairSortMode.Alphabetical => "Alphabetical",
        VisiblePairSortMode.VramUsage => "VRAM usage (descending)",
        VisiblePairSortMode.EffectiveVramUsage => "Effective VRAM usage (descending)",
        VisiblePairSortMode.TriangleCount => "Triangle count (descending)",
        VisiblePairSortMode.PreferredDirectPairs => "Preferred permissions & Direct pairs",
        _ => "Default",
    };

    private static string GetSortOnlineLabel(OnlinePairSortMode mode) => mode switch
    {
        OnlinePairSortMode.Alphabetical => "Alphabetical",
        OnlinePairSortMode.PreferredDirectPairs => "Preferred permissions & Direct pairs",
        _ => "Default",
    };
}