@namespace Oqtane.Modules.Admin.Modules
@using Oqtane.Interfaces
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IThemeService ThemeService
@inject IModuleService ModuleService
@inject IPageModuleService PageModuleService
@inject IStringLocalizer<Settings> Localizer

<TabStrip>
    <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
        @if (_containers != null)
        {
            <table class="table table-borderless">
                <tr>
                    <td>
                        <Label For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
                    </td>
                    <td>
                        <input id="title" type="text" name="Title" class="form-control" @bind="@_title" />
                    </td>
                </tr>
                <tr>
                    <td>
                        <Label For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
                    </td>
                    <td>
                        <select id="container" class="form-control" @bind="@_containerType">
                            @foreach (var container in _containers)
                            {
                                <option value="@container.TypeName">@container.Name</option>
                            }
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        <Label For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
                    </td>
                    <td>
                        <select id="allpages" class="form-control" @bind="@_allPages">
                            <option value="True">@Localizer["Yes"]</option>
                            <option value="False">@Localizer["No"]</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td>
                        <Label For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
                    </td>
                    <td>
                        <select id="page" class="form-control" @bind="@_pageId">
                            @foreach (Page p in PageState.Pages)
                            {
                                if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
                                {
                                    <option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
                                }
                            }
                        </select>
                    </td>
                </tr>
            </table>
        }
    </TabPanel>
    <TabPanel Name="Permissions" ResourceKey="Permissions">
        @if (_permissions != null)
        {
            <table class="table table-borderless">
                <tr>
                    <td>
                        <PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" Permissions="@_permissions" @ref="_permissionGrid" />
                    </td>
                </tr>
            </table>
        }
    </TabPanel>
    @if (_moduleSettingsType != null)
    {
        <TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
            @ModuleSettingsComponent
        </TabPanel>
    }
    @if (_containerSettingsType != null)
    {
        <TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
            @ContainerSettingsComponent
        </TabPanel>
    }
</TabStrip>
<button type="button" class="btn btn-success" @onclick="SaveModule">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>

@code {
    public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
    public override string Title => "Module Settings";

    private List<Theme> _themes;
    private List<ThemeControl> _containers = new List<ThemeControl>();
    private string _title;
    private string _containerType;
    private string _allPages = "false";
    private string _permissionNames = "";
    private string _permissions = null;
    private string _pageId;
    private PermissionGrid _permissionGrid;
    private Type _moduleSettingsType;
    private object _moduleSettings;
    private string _moduleSettingsTitle = "Module Settings";
    private RenderFragment ModuleSettingsComponent { get; set; }
    private Type _containerSettingsType;
    private object _containerSettings;
    private RenderFragment ContainerSettingsComponent { get; set; }

    protected override async Task OnInitializedAsync()
    {
        _title = ModuleState.Title;
        _themes = await ThemeService.GetThemesAsync();
        _containers = ThemeService.GetContainerControls(_themes, PageState.Page.ThemeType);
        _containerType = ModuleState.ContainerType;
        _allPages = ModuleState.AllPages.ToString();
        _permissions = ModuleState.Permissions;
        _permissionNames = ModuleState.ModuleDefinition.PermissionNames;
        _pageId = ModuleState.PageId.ToString();

        if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
        {
            // module settings type explicitly declared in IModule interface
            _moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
        }
        else
        {
            // legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
            _moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
        }
        if (_moduleSettingsType != null)
        {
            var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
            if (!string.IsNullOrEmpty(moduleobject.Title))
            {
                _moduleSettingsTitle = moduleobject.Title;
            }

            ModuleSettingsComponent = builder =>
            {
                builder.OpenComponent(0, _moduleSettingsType);
                builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
                builder.CloseComponent();
            };
        }

        var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
        if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
        {
            _containerSettingsType = Type.GetType(theme.ContainerSettingsType);
            if (_containerSettingsType != null)
            {
                ContainerSettingsComponent = builder =>
                {
                    builder.OpenComponent(0, _containerSettingsType);
                    builder.AddComponentReferenceCapture(1, inst => { _containerSettings = Convert.ChangeType(inst, _containerSettingsType); });
                    builder.CloseComponent();
                };
            }
        }
    }

    private async Task SaveModule()
    {
        if (!string.IsNullOrEmpty(_title))
        {
            var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
            pagemodule.PageId = int.Parse(_pageId);
            pagemodule.Title = _title;
            pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
            if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
            {
                pagemodule.ContainerType = string.Empty;
            }
            if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
            {
                pagemodule.ContainerType = string.Empty;
            }
            await PageModuleService.UpdatePageModuleAsync(pagemodule);
            await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);

            var module = ModuleState;
            module.AllPages = bool.Parse(_allPages);
            module.Permissions = _permissionGrid.GetPermissions();
            await ModuleService.UpdateModuleAsync(module);

            if (_moduleSettingsType != null)
            {
                if (_moduleSettings is ISettingsControl moduleSettingsControl)
                {
                    // module settings updated using explicit interface
                    await moduleSettingsControl.UpdateSettings();
                }
                else
                {
                    // legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
                    _moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
                }
            }

            if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
            {
                await containerSettingsControl.UpdateSettings();
            }

            NavigationManager.NavigateTo(NavigateUrl());
        }
        else
        {
            AddModuleMessage(Localizer["You Must Provide A Title For The Module"], MessageType.Warning);
        }
    }

}
