@using PteroConsole.NET
@using Moonlight.App.Services
@using Task = System.Threading.Tasks.Task
@using Moonlight.App.Helpers
@using Logging.Net
@using BlazorContextMenu
@using Moonlight.App.Database.Entities
@using Moonlight.App.Services.Interop

@inject ServerService ServerService
@inject NavigationManager NavigationManager
@inject AlertService AlertService
@inject ToastService ToastService
@inject ClipboardService ClipboardService
@inject MessageService MessageService
@inject SmartTranslateService SmartTranslateService

@implements IDisposable

<LazyLoader @ref="LazyLoader" Load="Refresh">
    @if (3 > AllBackups.Length)
    {
        <WButton 
            Text="@(SmartTranslateService.Translate("Create"))" 
            WorkingText="@(SmartTranslateService.Translate("Creating"))" 
            CssClasses="btn-primary mb-2" 
            OnClick="Create"></WButton>
    }
    else
    {
        <button class="btn btn-primary disabled mb-2" disabled=""><TL>Delete</TL></button>
    }
    <div class="table-responsive">
        <table class="table align-middle table-row-dashed fs-6 gy-5 dataTable no-footer">
            <thead>
            </thead>
            <tbody class="fw-semibold text-gray-600">
            @foreach (var backup in AllBackups)
            {
                <tr class="odd">
                    <td>
                        <div class="d-flex align-items-center">
                            <div class="ms-5">
                                <a class="text-gray-800 text-hover-primary fs-5 fw-bold">@(backup.Name)</a>
                            </div>
                        </div>
                    </td>
                    <td class="text-end pe-0">
                        <span class="fw-bold">@(backup.Uuid)</span>
                    </td>
                    <td class="text-end pe-0">
                        <span class="fw-bold">@(Formatter.FormatSize(backup.Bytes))</span>
                    </td>
                    <td class="text-end pe-0">
                        <span class="fw-bold ms-3">@backup.CreatedAt.Date.ToLongDateString(), @backup.CreatedAt.Date.ToLongTimeString()</span>
                    </td>
                    <td class="text-end">
                        @if (backup.Created)
                        {
                            <ContextMenuTrigger MenuId="triggerMenu" MouseButtonTrigger="MouseButtonTrigger.Both" Data="backup">
                                <button class="btn btn-sm btn-icon btn-light btn-active-light-primary me-2">
                                    <span class="svg-icon svg-icon-5 m-0">
                                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <rect x="10" y="10" width="4" height="4" rx="2" fill="currentColor"></rect>
                                            <rect x="17" y="10" width="4" height="4" rx="2" fill="currentColor"></rect>
                                            <rect x="3" y="10" width="4" height="4" rx="2" fill="currentColor"></rect>
                                        </svg>
                                    </span>
                                </button>
                            </ContextMenuTrigger>
                        }
                        else
                        {
                            <span class="fw-bold">
                                <TL>Backup is going to be created</TL>
                            </span>
                        }
                    </td>
                </tr>
            }
            </tbody>
        </table>
    </div>

    <ContextMenu Id="triggerMenu" CssClass="bg-secondary z-10">
        <Item Id="restore" OnClick="OnContextMenuClick">
            <TL>Restore</TL>
        </Item>
        <Item Id="copyurl" OnClick="OnContextMenuClick">
            <TL>Copy url</TL>
        </Item>
        <Item Id="download" OnClick="OnContextMenuClick">
            <TL>Download</TL>
        </Item>
        <Item Id="delete" OnClick="OnContextMenuClick">
            <TL>Delete</TL>
        </Item>
    </ContextMenu>
</LazyLoader>

@code
{
    [CascadingParameter]
    public PteroConsole Console { get; set; }

    [CascadingParameter]
    public Server CurrentServer { get; set; }

    private ServerBackup[]? AllBackups;

    private LazyLoader LazyLoader;

    protected override void OnInitialized()
    {
        MessageService.Subscribe<ServerBackups, ServerBackup>("wings.backups.create", this, (backup) =>
        {
            if (AllBackups == null)
                return Task.CompletedTask;

            if (AllBackups.Any(x => x.Id == backup.Id))
            {
                Task.Run(async () =>
                {
                    await Task.Delay(TimeSpan.FromSeconds(1));
                    await ToastService.Success(SmartTranslateService.Translate("Backup successfully created"));
                    await LazyLoader.Reload();
                });
            }
            
            return Task.CompletedTask;
        });

        MessageService.Subscribe<ServerBackups, ServerBackup>("wings.backups.createfailed", this, (backup) =>
        {
            if (AllBackups == null)
                return Task.CompletedTask;

            if (AllBackups.Any(x => x.Id == backup.Id))
            {
                Task.Run(async () =>
                {
                    await ToastService.Error(SmartTranslateService.Translate("Backup creation failed"));
                    await LazyLoader.Reload();
                });
            }
            
            return Task.CompletedTask;
        });

        MessageService.Subscribe<ServerBackups, ServerBackup>("wings.backups.delete", this, async (backup) =>
        {
            if (AllBackups == null)
                return;

            if (AllBackups.Any(x => x.Id == backup.Id))
            {
                Task.Run(async () =>
                {
                    await ToastService.Success(SmartTranslateService.Translate("Backup successfully deleted"));
                    await LazyLoader.Reload();
                });
            }
        });

        MessageService.Subscribe<ServerBackups, ServerBackup>("wings.backups.restore", this, async (backup) =>
        {
            if (AllBackups == null)
                return;

            if (AllBackups.Any(x => x.Id == backup.Id))
            {
                Task.Run(async () => { await ToastService.Success(SmartTranslateService.Translate("Backup successfully restored")); });
            }
        });
    }

    private async Task Refresh(LazyLoader lazyLoader)
    {
        await InvokeAsync(StateHasChanged);

        await lazyLoader.SetText(SmartTranslateService.Translate("Loading backups"));
        AllBackups = await ServerService.GetBackups(CurrentServer, true);

        await InvokeAsync(StateHasChanged);
    }

    private async Task Download(ServerBackup serverBackup)
    {
        try
        {
            var url = await ServerService.DownloadBackup(CurrentServer, serverBackup);

            NavigationManager.NavigateTo(url);
            await ToastService.Success(SmartTranslateService.Translate("Backup download successfully started"));
        }
        catch (Exception e)
        {
            Logger.Warn("Error starting backup download");
            Logger.Warn(e);
            await ToastService.Error(SmartTranslateService.Translate("Backup download failed"));
        }
    }

    private async Task CopyUrl(ServerBackup serverBackup)
    {
        try
        {
            var url = await ServerService.DownloadBackup(CurrentServer, serverBackup);

            await ClipboardService.CopyToClipboard(url);
            await AlertService.Success(
                SmartTranslateService.Translate("Success"), 
                SmartTranslateService.Translate("Backup URL successfully copied to your clipboard"));
        }
        catch (Exception e)
        {
            Logger.Warn("Error copying backup url");
            Logger.Warn(e);
            await ToastService.Error(SmartTranslateService.Translate("An unknown error occured while generating backup url"));
        }
    }

    private async Task Delete(ServerBackup serverBackup)
    {
        try
        {
            await ToastService.Info(SmartTranslateService.Translate("Backup deletion started"));
            await ServerService.DeleteBackup(CurrentServer, serverBackup);
        }
        catch (Exception e)
        {
            Logger.Warn("Error deleting backup");
            Logger.Warn(e);
            await ToastService.Error(SmartTranslateService.Translate("An unknown error occured while starting backup deletion"));
        }
    }

    private async Task Restore(ServerBackup serverBackup)
    {
        try
        {
            await ServerService.RestoreBackup(CurrentServer, serverBackup);

            await ToastService.Info(SmartTranslateService.Translate("Backup restore started"));
        }
        catch (Exception e)
        {
            Logger.Warn("Error restoring backup");
            Logger.Warn(e);
            await ToastService.Error(SmartTranslateService.Translate("An unknown error occured while restoring a backup"));
        }
    }

    private async Task Create()
    {
        try
        {
            await ToastService.Info(SmartTranslateService.Translate("Started backup creation"));
            var backup = await ServerService.CreateBackup(CurrentServer);

    /*
            
            // Modify the backup list so no reload needed. Also the create event will work
            var list = AllBackups!.ToList();
            list.Add(backup);
            AllBackups = list.ToArray();
            
            */

            await LazyLoader.Reload();
        }
        catch (Exception e)
        {
            Logger.Warn("Error creating backup");
            Logger.Warn(e);
            await ToastService.Error(SmartTranslateService.Translate("An unknown error has occured while creating a backup"));
        }
    }

    private async Task OnContextMenuClick(ItemClickEventArgs args)
    {
        var backup = (ServerBackup)args.Data;

        switch (args.MenuItem.Id)
        {
            case "delete":
                await Delete(backup);
                break;
            case "copyurl":
                await CopyUrl(backup);
                break;
            case "restore":
                await Restore(backup);
                break;
            case "download":
                await Download(backup);
                break;
        }

        await Refresh(LazyLoader);
    }

    public void Dispose()
    {
        MessageService.Unsubscribe("wings.backups.create", this);
        MessageService.Unsubscribe("wings.backups.createfailed", this);
        MessageService.Unsubscribe("wings.backups.restore", this);
        MessageService.Unsubscribe("wings.backups.delete", this);
    }
}