@namespace Oqtane.Modules.Admin.Files
@inherits ModuleBase
@inject IFolderService FolderService
@inject IFileService FileService
@inject NavigationManager NavigationManager
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer

@if (_folders != null)
{
    <TabStrip>
        <TabPanel Name="Settings" ResourceKey="Settings" Heading="Settings">
            <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
                <div class="container">
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
                        <div class="col-sm-9">
                            <select id="parent" class="form-select" @bind="@_parentId" required>
                                @if (PageState.QueryString.ContainsKey("id"))
                                {
                                    <option value="-1">&lt;@Localizer["NoParent"]&gt;</option>
                                }
                                @foreach (Folder folder in _folders)
                                {
                                    <option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
                                }
                            </select>
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
                        <div class="col-sm-9">
                            <input id="name" class="form-control" @bind="@_name" maxlength="256" required />
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Type">Type: </Label>
                        <div class="col-sm-9">
                            @if (PageState.QueryString.ContainsKey("id"))
                            {
                                <input id="type" class="form-control" readonly @bind="@_type" />
                            }
                            else
                            {
                                <select id="type" class="form-select" @bind="@_type" required>
                                    <option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
                                    <option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
                                </select>
                            }
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="capacity" HelpText="Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited." ResourceKey="Capacity">Capacity: </Label>
                        <div class="col-sm-9">
                            <input id="capacity" class="form-control" @bind="@_capacity" required />
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="cachecontrol" HelpText="Optionally provide a Cache-Control directive for this folder. For example 'public, max-age=60' indicates that files in this folder should be cached for 60 seconds. Please note that when caching is enabled, changes to files will not be immediately reflected in the UI." ResourceKey="CacheControl">Caching: </Label>
                        <div class="col-sm-9">
                            <input id="cachecontrol" class="form-control" @bind="@_cachecontrol" maxlength="50" />
                        </div>
                    </div>
                    <div class="row mb-1 align-items-center">
                        <Label Class="col-sm-3" For="imagesizes" HelpText="Optionally enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,400x400). Use * to indicate the folder supports all image sizes (not recommended)." ResourceKey="ImageSizes">Image Sizes: </Label>
                        <div class="col-sm-9">
                            <input id="imagesizes" class="form-control" @bind="@_imagesizes" maxlength="512" />
                        </div>
                    </div>
                </div>
                @if (PageState.QueryString.ContainsKey("id"))
                {
                    <br />
                    <AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
                }
            </form>
        </TabPanel>
        <TabPanel Name="Permissions" ResourceKey="Permissions" Heading="Permissions">
            <div class="container">
                <div class="row mb-1 align-items-center">
                    <PermissionGrid EntityName="@EntityNames.Folder" PermissionNames="@(PermissionNames.Browse + "," + PermissionNames.View + "," + PermissionNames.Edit)" PermissionList="@_permissions" @ref="_permissionGrid" />
                </div>
            </div>
        </TabPanel>
    </TabStrip>

    <br />
    @if (!_isSystem)
    {
        <button type="button" class="btn btn-success" @onclick="SaveFolder">@SharedLocalizer["Save"]</button>
        @((MarkupString)"&nbsp;")
    }
    <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
    @if (!_isSystem && PageState.QueryString.ContainsKey("id"))
    {
        @((MarkupString)"&nbsp;")
        <ActionDialog Header="Delete Folder" Message="Are You Sure You Wish To Delete This Folder?" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFolder())" ResourceKey="DeleteFolder" />
    }
}

@code {
    private ElementReference form;
    private bool validated = false;
    private List<Folder> _folders;
    private int _folderId = -1;
    private int _parentId = -1;
    private string _name;
    private string _type = FolderTypes.Private;
    private string _capacity = "0";
    private string _cachecontrol = string.Empty;
    private string _imagesizes = string.Empty;
    private bool _isSystem;
    private List<Permission> _permissions = null;
    private string _createdBy;
    private DateTime _createdOn;
    private string _modifiedBy;
    private DateTime _modifiedOn;

#pragma warning disable 649
    private PermissionGrid _permissionGrid;
#pragma warning restore 649

    public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;

    public override string Title => "Folder Management"; 

    protected override async Task OnInitializedAsync()
    {
        try
        {
            _folders = await FolderService.GetFoldersAsync(PageState.Site.SiteId);

            if (PageState.QueryString.ContainsKey("id"))
            {
                _folderId = Int32.Parse(PageState.QueryString["id"]);
                Folder folder = await FolderService.GetFolderAsync(_folderId);
                if (folder != null)
                {
                    _parentId = folder.ParentId ?? -1;
                    _name = folder.Name;
                    _type = folder.Type;
                    _capacity = folder.Capacity.ToString();
                    _cachecontrol = folder.CacheControl;
                    _imagesizes = folder.ImageSizes;
                    _isSystem = folder.IsSystem;
                    _permissions = folder.PermissionList;
                    _createdBy = folder.CreatedBy;
                    _createdOn = folder.CreatedOn;
                    _modifiedBy = folder.ModifiedBy;
                    _modifiedOn = folder.ModifiedOn;
                }
            }
            else
            {
                _parentId = _folders[0].FolderId;
            }
        }
        catch (Exception ex)
        {
            await logger.LogError(ex, "Error Loading Folder {FolderId} {Error}", _folderId, ex.Message);
            AddModuleMessage(Localizer["Error.Folder.Load"], MessageType.Error);
        }
    }

    private async Task SaveFolder()
    {
        validated = true;
        var interop = new Interop(JSRuntime);
        if (await interop.FormValid(form))
        {
            if (_name == string.Empty || _parentId == -1)
            {
                AddModuleMessage(Localizer["Message.Required.FolderParent"], MessageType.Warning);
                return;
            }

            if (!_name.IsPathOrFileValid())
            {
                AddModuleMessage(Localizer["Message.Folder.InvalidName"], MessageType.Warning);
                return;
            }

            try
            {
                Folder folder;

                if (_folderId != -1)
                {
                    folder = await FolderService.GetFolderAsync(_folderId);
                }
                else
                {
                    folder = new Folder();
                }

                if (_parentId == -1)
                {
                    folder.ParentId = null;
                }
                else
                {
                    folder.ParentId = _parentId;
                }

                // check for duplicate folder names
                if (_folders.Any(item => item.ParentId == folder.ParentId && item.Name == _name && item.FolderId != _folderId))
                {
                    AddModuleMessage(Localizer["Message.Folder.Duplicate"], MessageType.Warning);
                    return;
                }

                folder.SiteId = PageState.Site.SiteId;
                folder.Name = _name;
                folder.Type = _type;
                folder.Capacity = int.Parse(_capacity);
                folder.CacheControl = _cachecontrol;
                folder.ImageSizes = _imagesizes;
                folder.IsSystem = _isSystem;
                folder.PermissionList = _permissionGrid.GetPermissionList();

                if (_folderId != -1)
                {
                    folder = await FolderService.UpdateFolderAsync(folder);
                }
                else
                {
                    folder = await FolderService.AddFolderAsync(folder);
                }

                if (folder != null)
                {
                    await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
                    await logger.LogInformation("Folder Saved {Folder}", folder);
                    NavigationManager.NavigateTo(NavigateUrl());
                }
                else
                {
                    AddModuleMessage(Localizer["Error.Folder.Save"], MessageType.Error);
                }
            }
            catch (Exception ex)
            {
                await logger.LogError(ex, "Error Saving Folder {FolderId} {Error}", _folderId, ex.Message);
                AddModuleMessage(Localizer["Error.Folder.Save"], MessageType.Error);
            }
        }
        else
        {
            AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
        }
    }

    private async Task DeleteFolder()
    {
        try
        {
            bool isparent = false;
            foreach (Folder folder in _folders)
            {
                if (folder.ParentId == _folderId)
                {
                    isparent = true;
                    break;
                }
            }
            if (!isparent)
            {
                var files = await FileService.GetFilesAsync(_folderId);
                if (files.Count == 0)
                {
                    await FolderService.DeleteFolderAsync(_folderId);
                    await logger.LogInformation("Folder Deleted {Folder}", _folderId);
                    NavigationManager.NavigateTo(NavigateUrl());
                }
                else
                {
                    AddModuleMessage(Localizer["Message.Folder.Files.InvalidDelete"], MessageType.Warning);
                }
            }
            else
            {
                AddModuleMessage(Localizer["Message.Folder.Subfolders.InvalidDelete"], MessageType.Warning);
            }
        }
        catch (Exception ex)
        {
            await logger.LogError(ex, "Error Deleting Folder {Folder} {Error}", _folderId, ex.Message);
            AddModuleMessage(Localizer["Error.Folder.Delete"], MessageType.Error);
        }
    }
}