@using Moonlight.App.Helpers.Files
@using Moonlight.App.Helpers
@using Logging.Net
@using Moonlight.App.Services
@using Moonlight.App.Services.Interop
@using BlazorDownloadFile

@inject ToastService ToastService
@inject NavigationManager NavigationManager
@inject AlertService AlertService
@inject SmartTranslateService SmartTranslateService
@inject IBlazorDownloadFileService FileService

@if (Editing)
{
    <FileEditor @ref="Editor"
                InitialData="@EditorInitialData"
                Language="@EditorLanguage"
                OnCancel="() => Cancel()"
                OnSubmit="(_) => Cancel(true)"
                HideControls="false">
    </FileEditor>
}
else
{
    <div class="card mb-7">
        <div class="card-header border-0 my-2">
            <div class="card-title">
                <div class="d-flex flex-stack">
                    <FilePath Access="Access" OnPathChanged="OnComponentStateChanged" />
                </div>
            </div>
            <div class="card-toolbar">
                <div class="d-flex justify-content-end align-items-center">
                    @if (View != null && View.SelectedFiles.Any())
                    {
                        <div class="fw-bold me-5">
                            <span class="me-2">@(View.SelectedFiles.Length) <TL>selected</TL></span>
                        </div>
                        
                        <WButton Text="@(SmartTranslateService.Translate("Move"))"
                                 WorkingText="@(SmartTranslateService.Translate("Moving"))"
                                 CssClasses="btn-primary me-3"
                                 OnClick="StartMoveFiles">
                        </WButton>
                        
                        <WButton Text="@(SmartTranslateService.Translate("Compress"))"
                                 WorkingText="@(SmartTranslateService.Translate("Compressing"))"
                                 CssClasses="btn-primary me-3"
                                 OnClick="CompressMultiple">
                        </WButton>
                                                                                
                        <WButton Text="@(SmartTranslateService.Translate("Delete"))"
                                 WorkingText="@(SmartTranslateService.Translate("Deleting"))"
                                 CssClasses="btn-danger"
                                 OnClick="DeleteMultiple">
                        </WButton>
                    }
                    else
                    {
                        <button type="button" @onclick="Launch" class="btn btn-light-primary me-3">
                            <span class="svg-icon svg-icon-muted svg-icon-2">
                                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path opacity="0.3" d="M5 16C3.3 16 2 14.7 2 13C2 11.3 3.3 10 5 10H5.1C5 9.7 5 9.3 5 9C5 6.2 7.2 4 10 4C11.9 4 13.5 5 14.3 6.5C14.8 6.2 15.4 6 16 6C17.7 6 19 7.3 19 9C19 9.4 18.9 9.7 18.8 10C18.9 10 18.9 10 19 10C20.7 10 22 11.3 22 13C22 14.7 20.7 16 19 16H5ZM8 13.6H16L12.7 10.3C12.3 9.89999 11.7 9.89999 11.3 10.3L8 13.6Z" fill="currentColor"/>
                                    <path d="M11 13.6V19C11 19.6 11.4 20 12 20C12.6 20 13 19.6 13 19V13.6H11Z" fill="currentColor"/>
                                </svg>
                            </span>
                            <TL>Launch WinSCP</TL>
                        </button>

                        <button type="button" @onclick="CreateFile" class="btn btn-light-primary me-3">
                            <span class="svg-icon svg-icon-2">
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                                    <path fill="currentColor" d="M6 22h12a2 2 0 0 0 2-2V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2zm7-18 5 5h-5V4zM8 14h3v-3h2v3h3v2h-3v3h-2v-3H8v-2z"></path>
                                </svg>
                            </span>
                            <TL>New file</TL>
                        </button>

                        <button type="button" @onclick="CreateFolder" class="btn btn-light-primary me-3">
                            <span class="svg-icon svg-icon-2">
                                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z" fill="currentColor"></path>
                                    <path d="M10.4 3.60001L12 6H21C21.6 6 22 6.4 22 7V19C22 19.6 21.6 20 21 20H3C2.4 20 2 19.6 2 19V4C2 3.4 2.4 3 3 3H9.2C9.7 3 10.2 3.20001 10.4 3.60001ZM16 12H13V9C13 8.4 12.6 8 12 8C11.4 8 11 8.4 11 9V12H8C7.4 12 7 12.4 7 13C7 13.6 7.4 14 8 14H11V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V14H16C16.6 14 17 13.6 17 13C17 12.4 16.6 12 16 12Z" fill="currentColor"></path>
                                    <path opacity="0.3" d="M11 14H8C7.4 14 7 13.6 7 13C7 12.4 7.4 12 8 12H11V14ZM16 12H13V14H16C16.6 14 17 13.6 17 13C17 12.4 16.6 12 16 12Z" fill="currentColor"></path>
                                </svg>
                            </span>
                            <TL>New folder</TL>
                        </button>

                        <FileUpload Access="Access" OnUploadComplete="OnComponentStateChanged" />
                    }
                </div>
            </div>
        </div>
    </div>

    <div class="card card-body ps-9">
        <FileView @ref="View"
                  Access="Access"
                  ContextActions="Actions"
                  OnSelectionChanged="OnSelectionChanged"
                  OnElementClicked="OnElementClicked"
                  DisableScrolling="true">
        </FileView>
    </div>
    
    <FileSelectModal @ref="FileSelectModal"
                     OnlyFolder="true"
                     Title="@(SmartTranslateService.Translate("Select folder to move the file(s) to"))"
                     Access="MoveAccess"
                     OnSubmit="OnFileMoveSubmit">
    </FileSelectModal>
}

@code
{
    [Parameter]
    public FileAccess Access { get; set; }

    // File Editor
    private bool Editing = false;
    private string EditorInitialData = "";
    private string EditorLanguage = "";
    private FileData EditingFile;
    private FileEditor Editor;

    // File View
    private FileView? View;

    // File Move
    private FileAccess MoveAccess;
    private FileSelectModal FileSelectModal;
    private FileData? SingleMoveFile = null;
    
    // Config
    private ContextAction[] Actions = Array.Empty<ContextAction>();

    protected override void OnInitialized()
    {
        MoveAccess = (FileAccess)Access.Clone();
        
        List<ContextAction> actions = new();
        
        actions.Add(new()
        {
            Id = "rename",
            Name = "Rename",
            Action = async (x) =>
            {
                var name = await AlertService.Text(
                    SmartTranslateService.Translate("Rename"),
                    SmartTranslateService.Translate("Enter a new name"),
                    x.Name
                );

                if (name != x.Name)
                {
                    await Access.Move(x, Access.CurrentPath + name);
                }
                
                await View!.Refresh();
            }
        });
        
        actions.Add(new ()
        {
            Id = "download",
            Name = "Download",
            Action = async (x) =>
            {
                if (x.IsFile)
                {
                    try
                    {
                        var stream = await Access.DownloadStream(x);
                        await ToastService.Info(SmartTranslateService.Translate("Starting download"));
                        stream.Position = 0;
                        await FileService.DownloadFile(fileName: x.Name, stream: stream, contentType: "application/octet-stream");
                    }
                    catch (NotImplementedException)
                    {
                        var url = await Access.DownloadUrl(x);
                        NavigationManager.NavigateTo(url, true);
                        await ToastService.Info(SmartTranslateService.Translate("Starting download"));
                    }
                }
                else
                    await ToastService.Error(SmartTranslateService.Translate("You are not able to download folders using the moonlight file manager"));
            }
        });
        
        actions.Add(new()
        {
            Id = "compress",
            Name = "Compress",
            Action = async (x) =>
            {
                await Access.Compress(x);
                await View!.Refresh();
            }
        });
        
        actions.Add(new ()
        {
            Id = "decompress",
            Name = "Decompress",
            Action = async (x) =>
            {
                await Access.Decompress(x);
                await View!.Refresh();
            }
        });

        actions.Add(new()
        {
            Id = "move",
            Name = "Move",
            Action = async (x) =>
            {
                SingleMoveFile = x;
                await StartMoveFiles();
            }
        });
        
        actions.Add(new()
        {
            Id = "delete",
            Name = "Delete",
            Action = async (x) =>
            {
                await Access.Delete(x);
                await View!.Refresh();
            }
        });
        
        Actions = actions.ToArray();
    }

    private async Task<bool> OnElementClicked(FileData fileData)
    {
        if (fileData.IsFile)
        {
            EditorInitialData = await Access.Read(fileData);
            EditorLanguage = MonacoTypeHelper.GetEditorType(fileData.Name);
            EditingFile = fileData;

            Editing = true;

            await InvokeAsync(StateHasChanged);
            return true;
        }
        
        await InvokeAsync(StateHasChanged);
        return false;
    }

    private async void Cancel(bool save = false)
    {
        if (save)
        {
            var data = await Editor.GetData();
            await Access.Write(EditingFile, data);
        }

        Editing = false;
        await InvokeAsync(StateHasChanged);
    }

    private async Task Launch()
    {
        var url = await Access.GetLaunchUrl();
        NavigationManager.NavigateTo(url, true);
    }

    private async Task CreateFolder()
    {
        var name = await AlertService.Text(
            SmartTranslateService.Translate("Create a new folder"),
            SmartTranslateService.Translate("Enter a name"),
            ""
            );

        if (string.IsNullOrEmpty(name))
            return;

        await Access.MkDir(name);
        await View!.Refresh();
    }

    private async Task CreateFile()
    {
        var name = await AlertService.Text(
            SmartTranslateService.Translate("Create a new file"),
            SmartTranslateService.Translate("Enter a name"),
            ""
            );

        if (string.IsNullOrEmpty(name))
            return;

        await Access.Write(new FileData{IsFile = true, Name = name}, "");
        await View!.Refresh();
    }

    private async Task OnSelectionChanged()
    {
        await InvokeAsync(StateHasChanged);
    }

    private async Task StartMoveFiles()
    {
        await FileSelectModal.Show();
    }

    private async Task DeleteMultiple()
    {
        foreach (var data in View!.SelectedFiles)
        {
            await Access.Delete(data);
        }

        await View!.Refresh();
    }

    private async Task CompressMultiple()
    {
        await Access.Compress(View!.SelectedFiles);
        
        await View!.Refresh();
    }

    private async Task OnFileMoveSubmit(string path)
    {
        foreach (var sFile in View!.SelectedFiles)
        {
            await Access.Move(sFile, path + sFile.Name);
        }
        
        if (SingleMoveFile != null)
        {
            await Access.Move(SingleMoveFile, path + SingleMoveFile.Name);
            SingleMoveFile = null;
        }

        await View.Refresh();
    }

    // This method can be called by every component to refresh the view
    private async Task OnComponentStateChanged()
    {
        await View!.Refresh();
        await InvokeAsync(StateHasChanged);
    }
}