@using Iceshrimp.Frontend.Localization
@using Iceshrimp.Shared.Schemas.Web
@using Microsoft.Extensions.Localization
@using Iceshrimp.Assets.PhosphorIcons
@using Iceshrimp.Frontend.Core.Miscellaneous
@using Iceshrimp.Frontend.Core.Services
@inject ApiService                     Api;
@inject GlobalComponentSvc             Global;
@inject IStringLocalizer<Localization> Loc;

<div @ref="EmojiButton" class="emoji-entry" @onclick="SelectEmoji" @onclick:stopPropagation="true">
    <InlineEmoji Name="@Emoji.Name" Url="@Emoji.PublicUrl" Hover="@true" Size="3rem"/>
    <div class="emoji-details">
        <span class="emoji-name">@Emoji.Name</span>
        <span class="emoji-meta">
            @if (Remote)
            {
                @Emoji.Category
            }
            else
            {
                @foreach (var tag in Emoji.Tags)
                {
                    <span>@tag</span>
                }
            }
        </span>
        <span class="labels">
            @if (Emoji.Sensitive)
            {
                <Icon Name="Icons.EyeSlash" title="@Loc["Sensitive"]"/>
            }
            @if (!string.IsNullOrWhiteSpace(Emoji.License))
            {
                <Icon Name="Icons.Article" title="@Emoji.License"/>
            }
        </span>
    </div>
    <Menu @ref="EmojiMenu">
        @if (Remote)
        {
            <MenuElement Icon="Icons.Copy" OnSelect="Clone">
                <Text>@Loc["Clone"]</Text>
            </MenuElement>
        }
        else
        {
            <MenuElement Icon="Icons.CursorText" OnSelect="Rename">
                <Text>@Loc["Rename"]</Text>
            </MenuElement>
        }
        @if (Emoji.Sensitive)
        {
            <MenuElement Icon="Icons.Eye" OnSelect="MarkNotSensitive">
                <Text>@Loc["Mark as not sensitive"]</Text>
            </MenuElement>
        }
        else
        {
            <MenuElement Icon="Icons.EyeSlash" OnSelect="MarkAsSensitive">
                <Text>@Loc["Mark as sensitive"]</Text>
            </MenuElement>
        }
        @if (!Remote)
        {
            <MenuElement Icon="Icons.TextAa" OnSelect="SetTags">
                <Text>@Loc["Set tags"]</Text>
            </MenuElement>
            <MenuElement Icon="Icons.Folder" OnSelect="SetCategory">
                <Text>@Loc["Set category"]</Text>
            </MenuElement>
            <MenuElement Icon="Icons.Article" OnSelect="SetLicense">
                <Text>@Loc["Set license"]</Text>
            </MenuElement>
            <hr class="rule"/>
            <MenuElement Icon="Icons.Trash" OnSelect="Delete" Danger>
                <Text>@Loc["Delete"]</Text>
            </MenuElement>
        }
        <ClosingBackdrop OnClose="EmojiMenu.Close"></ClosingBackdrop>
    </Menu>
</div>

@code {
    [Parameter, EditorRequired] public required EmojiResponse    Emoji       { get; set; }
    [Parameter]                 public          bool             Remote      { get; set; }
    [Parameter]                 public          EventCallback    GetEmojis   { get; set; }
    private                                     ElementReference EmojiButton { get; set; }
    private                                     Menu             EmojiMenu   { get; set; } = null!;

    private void SelectEmoji() => EmojiMenu.Toggle(EmojiButton);

    private async Task Clone() =>
        await Global.ConfirmDialog?.Confirm(new EventCallback<bool>(this, CloneCallback), @Loc["Clone {0} from {1}?", Emoji.Name, Emoji.Category ?? ""], Icons.Copy, @Loc["Clone"])!;

    private async Task CloneCallback(bool confirm)
    {
        if (!confirm || !Remote || Emoji.Category == null) return;

        try
        {
            // Remote emojis endpoint sets EmojiResponse.Category to the emoji's host
            var res = await Api.Emoji.CloneEmojiAsync(Emoji.Name, Emoji.Category);
            if (res != null) await Global.NoticeDialog?.Display(Loc["Cloned {0} from {1}", Emoji.Name, Emoji.Category])!;
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task Rename() =>
        await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, RenameCallback), Loc["Rename emoji"], "", Emoji.Name, buttonText: Loc["Rename"])!;

    private async Task RenameCallback(string? name)
    {
        if (string.IsNullOrWhiteSpace(name)) return;

        try
        {
            var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Name = name });
            if (res != null)
            {
                Emoji.Name = res.Name;
                StateHasChanged();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task MarkSensitive(bool sensitive)
    {
        try
        {
            var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Sensitive = sensitive });
            if (res != null)
            {
                Emoji.Sensitive = res.Sensitive;
                StateHasChanged();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task MarkNotSensitive() => await MarkSensitive(false);

    private async Task MarkAsSensitive() => await MarkSensitive(true);

    private async Task SetTags() =>
        await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, SetTagsCallback), Loc["Set tags (separated by new line)"], "one\ntwo\nthree", string.Join("\n", Emoji.Tags), true, true)!;

    private async Task SetTagsCallback(string? tags)
    {
        if (tags == null) return;

        try
        {
            var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Tags = string.IsNullOrWhiteSpace(tags) ? [] : tags.Replace(" ", "").Split("\n").ToList() });
            if (res != null)
            {
                Emoji.Tags = res.Tags;
                StateHasChanged();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task SetCategory() =>
        await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, SetCategoryCallback), Loc["Set category"], "", Emoji.Category, true)!;

    private async Task SetCategoryCallback(string? category)
    {
        if (category == null) return;

        try
        {
            var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Category = category });
            if (res != null)
            {
                Emoji.Category = res.Category;
                await GetEmojis.InvokeAsync();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task SetLicense() =>
        await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, SetLicenseCallback), Loc["Set license"], "", Emoji.License, true, true)!;

    private async Task SetLicenseCallback(string? license)
    {
        if (license == null) return;

        try
        {
            var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { License = license });
            if (res != null)
            {
                Emoji.License = res.License;
                StateHasChanged();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task Delete() =>
        await Global.ConfirmDialog?.Confirm(new EventCallback<bool>(this, DeleteCallback), Loc["Delete {0}?", Emoji.Name], Icons.Trash, Loc["Delete"])!;

    private async Task DeleteCallback(bool delete)
    {
        if (!delete) return;
        try
        {
            var res = await Api.Emoji.DeleteEmojiAsync(Emoji.Id);
            if (res) await GetEmojis.InvokeAsync();
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }
}
