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

@if (_initialized)
{
    <form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
        <TabStrip ActiveTab="@_activetab">
            <TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
                @if (_containers != null)
                {
                    <div class="container">
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="module" HelpText="The name of the module" ResourceKey="Module">Module: </Label>
                            <div class="col-sm-9">
                                <input id="module" type="text" class="form-control" @bind="@_module" disabled />
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
                            <div class="col-sm-9">
                                <input id="title" type="text" class="form-control" @bind="@_title" required />
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="pane" HelpText="The pane where the module will be displayed" ResourceKey="Pane">Pane: </Label>
                            <div class="col-sm-9">
                                <select class="form-select" @bind="@_pane">
                                    @foreach (string pane in PageState.Page.Panes)
                                    {
                                        <option value="@pane">@pane Pane</option>
                                    }
                                </select>
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
                            <div class="col-sm-9">
                                <select id="container" class="form-select" @bind="@_containerType" required>
                                    @foreach (var container in _containers)
                                    {
                                        <option value="@container.TypeName">@container.Name</option>
                                    }
                                </select>
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this module is active" ResourceKey="EffectiveDate">Effective Date: </Label>
                            <div class="col-sm-9">
                                <input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="expiryDate" HelpText="The date that this module expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
                            <div class="col-sm-9">
                                <input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
                            <div class="col-sm-9">
                                <select id="allpages" class="form-select" @bind="@_allPages" required>
                                    <option value="True">@SharedLocalizer["Yes"]</option>
                                    <option value="False">@SharedLocalizer["No"]</option>
                                </select>
                            </div>
                        </div>
                        <div class="row mb-1 align-items-center">
                            <Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
                            <div class="col-sm-9">
                                <select id="page" class="form-select" @bind="@_pageId" required>
                                    @if (PageState.Page.UserId != null)
                                    {
                                        <option value="@PageState.Page.PageId">@(PageState.Page.Name)</option>
                                    }
                                    else
                                    {
                                        if (_pages != null)
                                        {
                                            foreach (Page p in _pages)
                                            {
                                                if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, p.PermissionList))
                                                {
                                                    <option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
                                                }
                                            }
                                        }
                                    }
                                </select>
                            </div>
                        </div>
                    </div>
                }
            </TabPanel>
            <TabPanel Name="Permissions" Heading="Permissions" ResourceKey="Permissions">
                @if (_permissions != null)
                {
                    <div class="container">
                        <div class="row mb-1 align-items-center">
                            <PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" PermissionList="@_permissions" @ref="_permissionGrid" />
                        </div>
                    </div>

                }
            </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>
        <br />
        <button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
        <NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
        <br />
        <br />
        <AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
    </form>
}

@code {
    public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;

    private bool _initialized = false;
    private ElementReference form;
    private bool validated = false;
    private List<ThemeControl> _containers = new List<ThemeControl>();
    private string _module;
    private string _title;
    private string _pane;
    private string _containerType;
    private string _allPages = "false";
    private string _permissionNames = "";
    private List<Permission> _permissions = null;
    private string _pageId;
    private PermissionGrid _permissionGrid;
    private Type _moduleSettingsType;
    private object _moduleSettings;
    private string _moduleSettingsTitle;
    private RenderFragment ModuleSettingsComponent { get; set; }
    private Type _containerSettingsType;
    private object _containerSettings;
    private RenderFragment ContainerSettingsComponent { get; set; }
    private string createdby;
    private DateTime createdon;
    private string modifiedby;
    private DateTime modifiedon;
    private DateTime? _effectivedate = null;
    private DateTime? _expirydate = null;
    private List<Page> _pages;
    private string _activetab = "";

    protected override async Task OnInitializedAsync()
    {
        SetModuleTitle(Localizer["ModuleSettings.Title"]);

        _title = ModuleState.Title;
        _moduleSettingsTitle = Localizer["ModuleSettings.Heading"];
        _pane = ModuleState.Pane;
        _containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
        _containerType = ModuleState.ContainerType;
        _allPages = ModuleState.AllPages.ToString();
        _permissions = ModuleState.PermissionList;
        _pageId = ModuleState.PageId.ToString();
        createdby = ModuleState.CreatedBy;
        createdon = ModuleState.CreatedOn;
        modifiedby = ModuleState.ModifiedBy;
        modifiedon = ModuleState.ModifiedOn;
        _effectivedate = Utilities.UtcAsLocalDate(ModuleState.EffectiveDate);
        _expirydate = Utilities.UtcAsLocalDate(ModuleState.ExpiryDate);
        _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);

        if (ModuleState.ModuleDefinition != null)
        {
            _module = ModuleState.ModuleDefinition.Name;
            _permissionNames = ModuleState.ModuleDefinition?.PermissionNames;

            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.AddAttribute(1, "RenderModeBoundary", RenderModeBoundary);
                    builder.AddComponentReferenceCapture(2, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
                    builder.CloseComponent();
                };
            }
        }
        else
        {
            AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
        }

        var theme = PageState.Site.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.AddAttribute(1, "RenderModeBoundary", RenderModeBoundary);
                    builder.AddComponentReferenceCapture(2, inst => { _containerSettings = Convert.ChangeType(inst, _containerSettingsType); });
                    builder.CloseComponent();
                };
            }
        }

        _initialized = true;
    }

    private async Task SaveModule()
    {

        validated = true;
        var interop = new Interop(JSRuntime);
        if (await interop.FormValid(form))
        {

            if (!string.IsNullOrEmpty(_title))
            {
                if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
                {
                    AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
                    return;
                }                
                var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
                pagemodule.PageId = int.Parse(_pageId);
                pagemodule.Title = _title;
                pagemodule.Pane = _pane;
                pagemodule.EffectiveDate = Utilities.LocalDateAndTimeAsUtc(_effectivedate);
                pagemodule.ExpiryDate = Utilities.LocalDateAndTimeAsUtc(_expirydate);
                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.PageModuleId = ModuleState.PageModuleId;
                module.PermissionList = _permissionGrid.GetPermissionList();
                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(PageState.ReturnUrl);
            }
            else
            {
                _activetab = "Settings";
                AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning);
            }
        }
        else
        {
            _activetab = "Settings";
            AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
        }
    }
}
