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

<div @ref="Attachment" class="attachment" @onclick="Select" @onclick:stopPropagation="true">
    @if (File.ContentType.StartsWith("image") || Constants.CommonImageExtensions.Any(e => File.Filename.EndsWith(e)))
    {
        <img class="thumbnail" src="@File.ThumbnailUrl" alt="@File.Description"/>
    }
    else if (File.ContentType.StartsWith("audio") || Constants.CommonAudioExtensions.Any(e => File.Filename.EndsWith(e)))
    {
        <Icon Name="Icons.FileAudio" Size="3em"/>
    }
    else if (File.ContentType.StartsWith("video") || Constants.CommonVideoExtensions.Any(e => File.Filename.EndsWith(e)))
    {
        <Icon Name="Icons.FileVideo" Size="3em"/>
    }
    else
    {
        <Icon Name="Icons.File" Size="3em"/>
    }
    @if (!File.ContentType.StartsWith("image") && Constants.CommonImageExtensions.All(e => !File.Filename.EndsWith(e)))
    {
        <span class="file-name">@File.Filename</span>
    }
    <div class="labels">
        @if (File.Description != null)
        {
            <Icon Name="Icons.ClosedCaptioning" title="@File.Description"/>
        }
        else
        {
            <Icon Name="Icons.Warning" title="@Loc["No alt text"]"/>
        }
        @if (File.Sensitive)
        {
            <Icon Name="Icons.EyeSlash" title="@Loc["Sensitive"]"/>
        }
    </div>
    <Menu @ref="AttachmentMenu">
        <MenuElement Icon="Icons.ArrowSquareOut" OnSelect="Open">
            <Text>@Loc["Open"]</Text>
        </MenuElement>
        @* TODO: Uncomment when FE supports media node *@
        @* @if (File.ContentType.StartsWith("image")) *@
        @* { *@
        @*     <MenuElement Icon="Icons.Paperclip" OnSelect="InsertInline"> *@
        @*         <Text>@Loc["Insert inline"]</Text> *@
        @*     </MenuElement> *@
        @* } *@
        @if (File.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>
        }
        <MenuElement Icon="Icons.ClosedCaptioning" OnSelect="SetAltText">
            <Text>@Loc["Set alt text"]</Text>
        </MenuElement>
        <MenuElement Icon="Icons.Trash" OnSelect="Remove">
            <Text>@Loc["Remove"]</Text>
        </MenuElement>
        <ClosingBackdrop OnClose="AttachmentMenu.Close"></ClosingBackdrop>
    </Menu>
</div>

@code {
    [Parameter, EditorRequired]  public required DriveFileResponse     File             { get; set; }
    [Parameter] [EditorRequired] public required EventCallback<string> AddInlineMedia   { get; set; }
    [Parameter, EditorRequired]  public required EventCallback<string> RemoveAttachment { get; set; }
    private                                      ElementReference      Attachment       { get; set; }
    private                                      Menu                  AttachmentMenu   { get; set; } = null!;

    private void Select() => AttachmentMenu.Toggle(Attachment, false);

    private void Open() => Js.InvokeVoidAsync("open", File.Url, "_blank");

    // TODO: Uncomment when FE supports media node
    // private async Task InsertInline()
    // {
    //     if (!File.ContentType.StartsWith("image/")) return;
    //     await AddInlineMedia.InvokeAsync(File.Url);
    // }

    private async Task MarkSensitive(bool sensitive)
    {
        try
        {
            var res = await Api.Drive.UpdateFileAsync(File.Id, new UpdateDriveFileRequest { Sensitive = sensitive });
            if (res != null)
            {
                File.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 SetAltText() =>
        await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, SetAltTextCallback), Loc["Set alt text"], "", File.Description, true, true)!;

    private async Task SetAltTextCallback(string? alt)
    {
        if (alt == null) return;

        try
        {
            var res = await Api.Drive.UpdateFileAsync(File.Id, new UpdateDriveFileRequest { Description = string.IsNullOrWhiteSpace(alt) ? null : alt });
            if (res != null)
            {
                File.Description = res.Description;
                StateHasChanged();
            }
        }
        catch (ApiException e)
        {
            await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
        }
    }

    private async Task Remove() =>
        await Global.ConfirmDialog?.Confirm(new EventCallback<bool>(this, RemoveCallback), Loc["Remove attachment?"], buttonText: Loc["Remove"])!;

    private async Task RemoveCallback(bool remove)
    {
        if (remove) await RemoveAttachment.InvokeAsync(File.Id);
    }
}