using CloudBuilder.Core.Service;
using CloudBuilder.Gui;
using CloudBuilder.Request.Security;
using CloudBuilder.Security.Data;
using CloudBuilder.Security.Entity;
using CloudBuilder.Security.Linkup;
using CloudBuilder.Security.Policy;
using Krypton.Toolkit;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CloudBuilder.Security.Gui
{
    public partial class SecurityActorOperationPage : AbstractPage
    {
        private SecurityActorData data;
        private SecurityActorEntity securityActorEntity;
        private SecurityMessagePolicy securityMessagePolicy;
        private SecurityActorRequest securityActorRequest;
        private SecurityGroupEntity[] securityGroups;
        private SecurityUserEntity[] securityUsers;
        public SecurityActorOperationPage()
        {
            InitializeComponent();
        }

        public override void FunctionLoaded()
        {
            try
            {
                base.FunctionLoaded();
                //初始化容器-------------------------------------
                securityMessagePolicy = ServiceHelper.GetTypeService<SecurityMessagePolicy>()!;
                securityActorRequest = ServiceHelper.GetTypeService<SecurityActorRequest>();

                //界面初始化
                InitGui();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }


        private void InitGui()
        {
            InitBindingContext();

            InitComBox();

            InitDisplayMode();

            this.ParentAbstractForm.AcceptButton = this.searchBut;
            this.ParentAbstractForm.CancelButton = this.resetBut;
        }

        private void InitComBox()
        {
            try
            {
                SecurityGroupRequest securityGroupRequest = ServiceHelper.GetTypeService<SecurityGroupRequest>();
                securityGroups = securityGroupRequest.FindAll();

                deselectedGv.SetColumnDataSource(groupLocalNameCol, securityGroups, SecurityGroupEntity.GROUP_LOCAL_NAME, SecurityGroupEntity.GROUP_NAME, true);
                selectedGv.SetColumnDataSource(groupLocalNameSelectedCol, securityGroups, SecurityGroupEntity.GROUP_LOCAL_NAME, SecurityGroupEntity.GROUP_NAME, true);

                SecurityUserRequest securityUserRequest = ServiceHelper.GetTypeService<SecurityUserRequest>();
                securityUsers = securityUserRequest.FindAll();

                deselectedUserGv.SetColumnDataSource(userLocalNameCol, securityUsers, SecurityUserEntity.USER_LOCAL_NAME, SecurityUserEntity.USER_NAME, true);
                selectedUserGv.SetColumnDataSource(userLocalNameSelectedCol, securityUsers, SecurityUserEntity.USER_LOCAL_NAME, SecurityUserEntity.USER_NAME, true);
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// 有特殊要求的UI控件初始化设置,Init与Add配对后，使用guiOperateHelper管理
        /// </summary>
        private void InitBindingContext()
        {
            //需要绑定数据
            guiBindingContext = new GuiBindingContext();

            InitPermission();

            actorNameTxt.Set(SecurityActorEntity.ACTOR_NAME, actorNameLabel.Text, EnumEditModeColor.Required);
            actorLocalNameTxt.Set(SecurityActorEntity.ACTOR_LOCAL_NAME);
            actorEngNameTxt.Set(SecurityActorEntity.ACTOR_ENG_NAME);

            selectedGv.InitColumn(false, true);
            deselectedGv.InitColumn(false, true);

            selectedUserGv.InitColumn(false, true);
            deselectedUserGv.InitColumn(false, true);

            guiOperateHelper = new GuiOperateHelper();
        }

        private void InitPermission()
        {
            createBut.Set(SecurityPermissionPolicy.SecurityActor, Operate.Insert);
            amendBut.Set(SecurityPermissionPolicy.SecurityActor, Operate.Update);
            deleteBut.Set(SecurityPermissionPolicy.SecurityActor, Operate.Delete);
        }

        /// <summary>
        /// 每次从别的界面进入时执行，发生在FunctionLoaded之后
        /// </summary>
        /// <param name="param"></param>
        public override void FunctionActivated(object param)
        {
            try
            {
                if (param == null)
                {
                    actorNameSearchTxt.Focus();
                    return;
                }

                InitDisplayMode();

                SecurityActorOperationLinkup linkup = null;

                if (param is SecurityActorOperationLinkup)
                {
                    linkup = (SecurityActorOperationLinkup)param;
                }

                this.DisplayMode = (GuiDisplayMode)linkup.DisplayMode;

                actorNameSearchTxt.Text = linkup.ActorName;

                if (this.DisplayMode == GuiDisplayMode.View)
                {
                    Search();
                }
                else if (this.DisplayMode == GuiDisplayMode.Create)
                {
                    Create();
                }
                else if (this.DisplayMode == GuiDisplayMode.Amend)
                {
                    Search();
                    Amend();
                }

                actorNameSearchTxt.Focus();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        public override void FunctionSelected()
        {
            this.ParentAbstractForm.AcceptButton = this.searchBut;
            if (!IsDialog)
                this.ParentAbstractForm.CancelButton = this.resetBut;
            else
                this.ParentAbstractForm.CancelButton = this.cancelBut;

            actorNameSearchTxt.Focus();
        }

        public override bool FunctionDeactivating()
        {
            if (this.DisplayMode == GuiDisplayMode.View)
            {
                return true;
            }
            else
            {
                return CancelEditing();
            }
        }

        private bool CancelEditing()
        {
            DialogResult result = ShowMessageBox.ShowOption(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM_CANCEL), securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM));

            //从外部跳转(非mainKryptonNavigator)，result第一次不生效？，所以再执行一次生效
            if (result == DialogResult.Cancel)
            {
                result = ShowMessageBox.ShowOption(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM_CANCEL), securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM));
            }

            if (result == DialogResult.No)
            {
                return false;
            }

            Cancel();

            return true;
        }

        private void InitDisplayMode()
        {
            this.DisplayMode = GuiDisplayMode.View;

            SetDisplayMode();
        }

        private void SetDisplayMode()
        {
            if (this.DisplayMode == GuiDisplayMode.View)
            {
                savePanel.Visible = false;
                operationPanel.Visible = true;

                guiOperateHelper.EnableControls(true, topPanel);
                guiOperateHelper.EnableControls(false, contentPanel);
                //查詢有記錄時,修改等控件有效
                if (securityActorEntity != null)
                    guiOperateHelper.EnableControls(true, bottomPanel);
                else
                    guiOperateHelper.EnableControls(false, bottomPanel);
            }
            else if (this.DisplayMode == GuiDisplayMode.Amend || this.DisplayMode == GuiDisplayMode.Create)
            {
                savePanel.Visible = true;
                operationPanel.Visible = false;

                guiOperateHelper.EnableControls(false, topPanel);
                guiOperateHelper.EnableControls(true, bottomPanel, contentPanel);

                if (this.DisplayMode == GuiDisplayMode.Amend) guiOperateHelper.EnableControls(false, actorNameTxt);
            }

            guiOperateHelper.EnableControls(false, deselectedGv, selectedGv);
        }

        private void PackUIToEntity()
        {
            guiBindingContext.DataPack();

            SecurityGroupEntity[] groups = selectedGv.GetAllRows<SecurityGroupEntity>();
            if (groups != null && groups.Length > 0)
            {
                data.SecurityActorGroups = groups.Select(x => new SecurityActorGroupViewEntity() { ActorName = actorNameTxt.Text, GroupName = x.GroupName }).ToArray();
            }
            else
                data.SecurityActorGroups = null;

            SecurityUserEntity[] users = selectedUserGv.GetAllRows<SecurityUserEntity>();
            if (users != null && users.Length > 0)
            {
                data.SecurityUserActors = users.Select(x => new SecurityUserActorViewEntity() { ActorName = actorNameTxt.Text, UserName = x.UserName, UserLocalName = string.Empty }).ToArray();
            }
            else
                data.SecurityUserActors = null;
        }

        private bool SaveValidate()
        {
            if (!guiOperateHelper.CheckValidate(this.mainPanel)) return false;

            return true;
        }

        private void Search()
        {
            try
            {
                if (string.IsNullOrEmpty(actorNameSearchTxt.Text)) return;

                Reset();

                data = securityActorRequest.FindByKey(actorNameSearchTxt.Text);

                if (data == null || data.SecurityActor == null)
                {
                    ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                }
                else
                {
                    securityActorEntity = data.SecurityActor;

                    PackEntityToUI();

                    SetDisplayMode();
                }
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void Create()
        {
            this.DisplayMode = GuiDisplayMode.Create;

            guiOperateHelper.ResetControls(this.mainPanel);

            SetDisplayMode();

            data = new SecurityActorData();
            securityActorEntity = new SecurityActorEntity()
            {
                CreatedBy = string.Empty,
                UpdatedBy = string.Empty,
                CreatedDatetime = DateTime.Now,
                UpdatedDatetime = DateTime.Now,
            };
            data.SecurityActor = securityActorEntity;

            PackEntityToUI();

            actorNameTxt.Focus();
        }

        private void Amend()
        {
            this.DisplayMode = GuiDisplayMode.Amend;

            SetDisplayMode();
        }

        private void PackEntityToUI()
        {
            guiBindingContext.DataBind(data.SecurityActor, this);

            SecurityGroupEntity[] allGroups = securityGroups;
            SecurityGroupEntity[] deselecteds = null;
            SecurityGroupEntity[] selecteds = null;
            if (data.SecurityActorGroups != null)
            {
                deselecteds = allGroups.Where(x => !data.SecurityActorGroups.Select(y => y.GroupName).Contains(x.GroupName)).ToArray();
                selecteds = allGroups.Where(x => data.SecurityActorGroups.Select(y => y.GroupName).Contains(x.GroupName)).ToArray();
            }
            else
            {
                deselecteds = allGroups;
            }

            deselectedGv.SetDataSource(deselecteds);
            selectedGv.SetDataSource(selecteds);

            SecurityUserEntity[] allUsers = securityUsers;
            SecurityUserEntity[] deselectedUsers = null;
            SecurityUserEntity[] selectedUsers = null;
            if (data.SecurityUserActors != null)
            {
                deselectedUsers = allUsers.Where(x => !data.SecurityUserActors.Select(y => y.UserName).Contains(x.UserName)).ToArray();
                selectedUsers = allUsers.Where(x => data.SecurityUserActors.Select(y => y.UserName).Contains(x.UserName)).ToArray();
            }
            else
            {
                deselectedUsers = allUsers;
            }

            deselectedUserGv.SetDataSource(deselectedUsers);
            selectedUserGv.SetDataSource(selectedUsers);
        }

        private void Reset()
        {
            this.DisplayMode = GuiDisplayMode.View;

            securityActorEntity = null;

            guiOperateHelper.ResetControls(this.contentPanel);

            SetDisplayMode();

            actorNameSearchTxt.Focus();
        }

        public void Cancel()
        {
            if (!string.IsNullOrEmpty(actorNameSearchTxt.Text))
                Search();
            else
                Reset();

        }


        private void actorNameSearchBut_Click(object sender, EventArgs e)
        {
            try
            {
                AbstractForm dialog = GetAbstractDialog(typeof(SecurityActorEnquiryPage).Name);

                if (DialogResult.OK != dialog.ShowDialog()) return;

                actorNameSearchTxt.Text = ((SecurityActorEntity[])dialog.OutputData)[0].ActorName;

                Search();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void searchBut_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(actorNameSearchTxt.Text))
                {
                    ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_VALID_INPUT, GuiOperateHelper.GetLabelText(actorNameSearchLabel.Text)));
                    this.actorNameSearchTxt.Focus();
                    return;
                }
                this.DisplayMode = GuiDisplayMode.View;

                Search();

            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void resetBut_Click(object sender, EventArgs e)
        {
            try
            {
                guiOperateHelper.ResetControls(this.topPanel);
                Reset();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void createBut_Click(object sender, EventArgs e)
        {
            HandleException(() => Create());
        }

        private void amendBut_Click(object sender, EventArgs e)
        {
            HandleException(() => Amend());
        }

        private void deleteBut_Click(object sender, EventArgs e)
        {
            try
            {
                if (securityActorEntity == null)
                {
                    ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                    return;
                }

                if (DialogResult.Yes != ShowMessageBox.ShowOption(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_CONFIRM_DEL_NULL), securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_DELETE))) return;

                securityActorRequest.Delete(securityActorEntity.ActorName);

                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_SUCCEED_DELETED_NULL));

                Reset();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void saveBut_Click(object sender, EventArgs e)
        {
            try
            {
                if (!SaveValidate()) return;

                PackUIToEntity();


                if (this.DisplayMode == GuiDisplayMode.Create)
                    securityActorRequest.Insert(data);
                else
                    securityActorRequest.Update(data);


                ShowMessageBox.ShowInfo((this.DisplayMode == GuiDisplayMode.Create) ?
                    securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_SUCCEED_CREATED_NULL) :
                    securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_SUCCEED_UPDATED_NULL));

                actorNameSearchTxt.Text = securityActorEntity.ActorName;
                Search();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        private void cancelBut_Click(object sender, EventArgs e)
        {
            HandleException(() => CancelEditing());

        }

        private void selectedBut_Click(object sender, EventArgs e)
        {
            if (selectedGv.RowCount <= 0 || selectedGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityGroupEntity[] securityGroups = selectedGv.GetSelectedCellsData<SecurityGroupEntity>();
            selectedGv.DeleteRows(selectedGv.SelectedCells);

            deselectedGv.AddRow<SecurityGroupEntity>(securityGroups);
        }

        private void deselectedBut_Click(object sender, EventArgs e)
        {
            if (deselectedGv.RowCount <= 0 || deselectedGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityGroupEntity[] securityGroups = deselectedGv.GetSelectedCellsData<SecurityGroupEntity>();
            deselectedGv.DeleteRows(deselectedGv.SelectedCells);

            selectedGv.AddRow<SecurityGroupEntity>(securityGroups);
        }

        private void userSelectedBut_Click(object sender, EventArgs e)
        {
            if (selectedUserGv.RowCount <= 0 || selectedUserGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityUserEntity[] securityUsers = selectedUserGv.GetSelectedCellsData<SecurityUserEntity>();
            selectedUserGv.DeleteRows(selectedUserGv.SelectedCells);

            deselectedUserGv.AddRow<SecurityUserEntity>(securityUsers);
        }

        private void userDeselectedBut_Click(object sender, EventArgs e)
        {
            if (deselectedUserGv.RowCount <= 0 || deselectedUserGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityUserEntity[] securityUsers = deselectedUserGv.GetSelectedCellsData<SecurityUserEntity>();
            deselectedUserGv.DeleteRows(deselectedGv.SelectedCells);

            selectedUserGv.AddRow<SecurityUserEntity>(securityUsers);
        }


        private void selectedGv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (selectedGv.RowCount <= 0 || selectedGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityGroupEntity data = selectedGv.GetRowData<SecurityGroupEntity>(selectedGv.SelectedCells[0].RowIndex);

            DisplayPage(GuiDisplayMode.View, data.GroupName);
        }

        private void DisplayPage(GuiDisplayMode mode, string groupName)
        {
            SecurityGroupOperationLinkup linkupData = new SecurityGroupOperationLinkup();
            linkupData.DisplayMode = Convert.ToInt32(mode);
            linkupData.GroupName = groupName;

            this.DisplayAbstractPage(typeof(SecurityGroupOperationPage).Name, linkupData);
        }

        private void deselectedGv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (deselectedGv.RowCount <= 0 || deselectedGv.SelectedCells.Count <= 0)
            {
                ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_WS_RECORD_NOT_FOUND));
                return;
            }

            SecurityGroupEntity data = deselectedGv.GetRowData<SecurityGroupEntity>(deselectedGv.SelectedCells[0].RowIndex);

            DisplayPage(GuiDisplayMode.View, data.GroupName);
        }
    }
}
