@namespace Oqtane.Modules.Controls
@using System.Text.Json
@inherits LocalizableComponent
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject NavigationManager NavigationManager

@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Interactive)
{
    @if (_visible)
    {
        <div class="app-actiondialog">
            <div class="modal" tabindex="-1" role="dialog">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">@Header</h5>
                            <button type="button" class="btn-close" aria-label="Close" @onclick="DisplayModal"></button>
                        </div>
                        <div class="modal-body">
                            <p>@Message</p>
                        </div>
                        <div class="modal-footer">
                            @if (!string.IsNullOrEmpty(Action))
                            {
                                <button type="button" class="@ConfirmClass" @onclick="Confirm">@((MarkupString)_iconSpan) @Text</button>
                            }
                            <button type="button" class="@CancelClass" @onclick="DisplayModal">@SharedLocalizer["Cancel"]</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    }
    @if (_authorized)
    {
        if (Disabled)
        {
            <button type="button" class="@Class" disabled>@((MarkupString)_openIconSpan) @_openText</button>
        }
        else
        {
            <button type="button" class="@Class" @onclick="DisplayModal">@((MarkupString)_openIconSpan) @_openText</button>
        }
    }
}
else
{
    @if (_visible)
    {
        <div class="app-actiondialog">
            <div class="modal" tabindex="-1" role="dialog">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <form class="app-form-inline" method="post" @formname="@($"ActionDialogCloseForm:{ModuleState.PageModuleId}:{Id}")" @onsubmit="DisplayModal" data-enhance>
                            <input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
                            <div class="modal-header">
                                <h5 class="modal-title">@Header</h5>
                                <button type="submit" class="btn-close" aria-label="Close"></button>
                            </div>
                        </form>
                        <div class="modal-body">
                            <p>@Message</p>
                        </div>
                        <div class="modal-footer">
                            @if (!string.IsNullOrEmpty(Action))
                            {
                                <form method="post" @formname="@($"ActionDialogConfirmForm:{ModuleState.PageModuleId}:{Id}")" @onsubmit="Confirm" data-enhance>
                                    <input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
                                    <button type="submit" class="@ConfirmClass">@((MarkupString)_iconSpan) @Text</button>
                                </form>
                            }
                            <form method="post" @formname="@($"ActionDialogCancelForm:{ModuleState.PageModuleId}:{Id}")" @onsubmit="DisplayModal" data-enhance>
                                <input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
                                <button type="submit" class="@CancelClass">@SharedLocalizer["Cancel"]</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    }
    @if (_authorized)
    {
        if (Disabled)
        {
            <button type="button" class="@Class" disabled>@((MarkupString)_openIconSpan) @_openText</button>
        }
        else
        {
            <form method="post" class="app-form-inline" @formname="@($"ActionDialogActionForm:{ModuleState.PageModuleId}:{Id}")" @onsubmit="DisplayModal" data-enhance>
                <input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
                <button type="submit" class="@Class">@((MarkupString)_openIconSpan) @_openText</button>
            </form>
        }
    }
}

@code {
    private bool _visible = false;
    private List<Permission> _permissions;
    private bool _editmode = false;
    private bool _authorized = false;
    private string _iconSpan = string.Empty;
    private string _openIconSpan = string.Empty;
    private string _openText = string.Empty;

    [Parameter]
    public string Header { get; set; } // required

    [Parameter]
    public string Message { get; set; } // required

    [Parameter]
    public string Text { get; set; } // optional - defaults to Action if not specified

    [Parameter]
    public string Action { get; set; } // optional

    [Parameter]
    public SecurityAccessLevel? Security { get; set; } // optional - can be used to explicitly specify SecurityAccessLevel

    [Parameter]
    public string Permissions { get; set; } // deprecated - use PermissionList instead

    [Parameter]
    public List<Permission> PermissionList { get; set; } // optional - can be used to specify permissions

    [Parameter]
    public string Class { get; set; } // optional

    [Parameter]
    public string ConfirmClass { get; set; } // optional - for Confirm modal button

    [Parameter]
    public string CancelClass { get; set; } // optional - for Cancel modal button

    [Parameter]
    public bool Disabled { get; set; } // optional

    [Parameter]
    public string EditMode { get; set; } // optional - specifies if an authorized user must be in edit mode to see the action - default is false

    [Parameter]
    public Action OnClick { get; set; } // required if an Action is specified - executes a method in the calling component

    [Parameter]
    public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon

    [Parameter]
    public bool IconOnly { get; set; } // optional - specifies only icon in opening link

    [Parameter]
    public string Id { get; set; } // optional - specifies a unique id for the compoment - required when there are multiple component instances on a page in static rendering

    protected override void OnInitialized()
    {
        if (!string.IsNullOrEmpty(Permissions))
        {
            PermissionList = JsonSerializer.Deserialize<List<Permission>>(Permissions);
        }
    }

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        if (string.IsNullOrEmpty(Text))
        {
            Text = Action;
        }

        if (string.IsNullOrEmpty(Class))
        {
            Class = "btn btn-success";
        }

        if (string.IsNullOrEmpty(ConfirmClass))
        {
            ConfirmClass = Class;
        }

        if (string.IsNullOrEmpty(CancelClass))
        {
            CancelClass = "btn btn-secondary";
        }

        if (!string.IsNullOrEmpty(EditMode))
        {
            _editmode = bool.Parse(EditMode);
        }

        Text = Localize(nameof(Text), Text);
        Header = Localize(nameof(Header), Header);
        Message = Localize(nameof(Message), Message);

        _openText = Text;

        if (!string.IsNullOrEmpty(IconName))
        {
            if (IconOnly)
            {
                _openText = string.Empty;
            }

            // Check if IconName starts with "oi oi-"
            bool startsWithOiOi = IconName.StartsWith("oi oi-");

            if (!startsWithOiOi && !IconName.Contains(" "))
            {
                IconName = "oi oi-" + IconName;
            }
            _openIconSpan = $"<span class=\"{IconName}\"></span>{(IconOnly ? "" : "&nbsp")}";
            _iconSpan = $"<span class=\"{IconName}\"></span>&nbsp";
        }

        _permissions = (PermissionList == null) ? ModuleState.PermissionList : PermissionList;
        _authorized = IsAuthorized();

        if (string.IsNullOrEmpty(Id)) Id = "1";

        if (PageState.QueryString.ContainsKey("dialog"))
        {
            _visible = (PageState.QueryString["dialog"] == Id); 
        }
    }

    private bool IsAuthorized()
    {
        bool authorized = false;
        if (PageState.EditMode || !_editmode)
        {
            SecurityAccessLevel security = SecurityAccessLevel.Host;
            if (Security == null)
            {
                string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0) + ",", Action + ",");
                Type moduleType = Type.GetType(typename);
                if (moduleType != null)
                {
                    var moduleobject = Activator.CreateInstance(moduleType) as IModuleControl;
                    security = moduleobject.SecurityAccessLevel;
                }
                else
                {
                    security = SecurityAccessLevel.Anonymous; // occurs when an action does not have a corresponding module control
                }
            }
            else
            {
                security = Security.Value;
            }
            switch (security)
            {
                case SecurityAccessLevel.Anonymous:
                    authorized = true;
                    break;
                case SecurityAccessLevel.View:
                    authorized = UserSecurity.IsAuthorized(PageState.User,PermissionNames.View, _permissions);
                    break;
                case SecurityAccessLevel.Edit:
                    authorized = UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, _permissions);
                    break;
                case SecurityAccessLevel.Admin:
                    authorized = UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin);
                    break;
                case SecurityAccessLevel.Host:
                    authorized = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
                    break;
            }
        }
        return authorized;
    }

    private void DisplayModal()
    {
        _visible = !_visible;
        if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Interactive)
        {
            StateHasChanged();
        }
        else
        {
            var parameters = new Dictionary<string, string>(PageState.QueryString);
            if (parameters.ContainsKey("dialog")) parameters.Remove("dialog");
            if (_visible) parameters.Add("dialog", Id);
            NavigationManager.NavigateTo(PageState.Route.AbsolutePath + Utilities.CreateQueryString(parameters));
        }
    }

    private void Confirm()
    {
        OnClick();
        DisplayModal();
    }
}
