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 CloudBuilder.Security.SearchCriteria;
using DocumentFormat.OpenXml.Wordprocessing;
using Krypton.Toolkit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Extensions;
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 SecurityFunctionOperationPage : AbstractPage
    {
        private SecurityMessagePolicy securityMessagePolicy;
        private SecurityFunctionRequest securityFunctionRequest;
        private SecurityFunctionDisplayData securityFunctionEntity;
        private SecurityFunctionData data;
        public SecurityFunctionOperationPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 第一次加载时执行，只执行一次
        /// </summary>
        public override void FunctionLoaded()
        {
            try
            {
                base.FunctionLoaded();
                //初始化容器-------------------------------------
                securityMessagePolicy = ServiceHelper.GetTypeService<SecurityMessagePolicy>()!;
                securityFunctionRequest = ServiceHelper.GetTypeService<SecurityFunctionRequest>();

                //界面初始化
                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;
        }

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

            InitPermission();

            functionNameTxt.Set(SecurityFunctionEntity.FUNCTION_NAME, functionNameLabel.Text, EnumEditModeColor.Required);
            functionEngNameTxt.Set(SecurityFunctionEntity.FUNCTION_ENG_NAME, functionEngNameLabel.Text, EnumEditModeColor.Required);
            functionLocalNameTxt.Set(SecurityFunctionEntity.FUNCTION_LOCAL_NAME, functionLocalNameLabel.Text, EnumEditModeColor.Required);
            pageNameTxt.Set(SecurityFunctionEntity.PAGE_NAME);
            apiRouteTxt.Set(SecurityFunctionEntity.API_ROUTE);
            pageUrlTxt.Set(SecurityFunctionEntity.PAGE_URL);
            iconTxt.Set(SecurityFunctionEntity.ICON);
            functionIndcCombo.Set(SecurityFunctionEntity.FUNCTION_INDC, functionIndcLabel.Text, EnumEditModeColor.Required);
            permissionNameTxt.Set(SecurityFunctionDisplayData.PERMISSION_NAME);

            dataGv.InitColumn(false, true);
            dataSonGv.InitColumn(false, true);

            guiOperateHelper = new GuiOperateHelper();
        }

        private void InitComBox()
        {
            functionIndcCombo.SetDataSource(YesNoPolicy.GetInstance().GetComposeMessages(), true);
        }

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

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

                InitDisplayMode();

                SecurityFunctionOperationLinkup linkup = null;

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

                this.DisplayMode = (GuiDisplayMode)linkup.DisplayMode;

                functionNameSearchTxt.Text = linkup.FunctionName;

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

                functionNameSearchTxt.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;

            functionNameSearchTxt.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 (securityFunctionEntity != 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, functionNameTxt);

                guiOperateHelper.EnableControls(false, dataGv);
                functionLocalNameSonCol.ReadOnly = true;
                functionLocalNameSonCol.DefaultCellStyle.BackColor = System.Drawing.Color.Silver;
                functionNameSonCol.ReadOnly = true;
                functionNameSonCol.DefaultCellStyle.BackColor = System.Drawing.Color.Silver;
                dataGv.DefaultCellStyle.BackColor = System.Drawing.Color.Silver;
            }
        }

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

            SecurityFunctionMapViewEntity[] securityFunctionMapParents = dataGv.GetAllRows<SecurityFunctionMapViewEntity>();

            if (securityFunctionMapParents == null || securityFunctionMapParents.Length == 0)
                data.SecurityFunctionMapParents = null;
            else
                data.SecurityFunctionMapParents = securityFunctionMapParents.Select(x => new SecurityFunctionMapViewEntity()
                {
                    ParentFunctionName = x.ParentFunctionName,
                    SonFunctionName = functionNameTxt.Text
                }).ToArray();

            SecurityFunctionMapViewEntity[] securityFunctionMapSons = dataSonGv.GetAllRows<SecurityFunctionMapViewEntity>();

            if (securityFunctionMapSons == null || securityFunctionMapSons.Length == 0)
                data.SecurityFunctionMapSons = null;
            else
                data.SecurityFunctionMapSons = securityFunctionMapSons.Select(x => new SecurityFunctionMapViewEntity()
                {
                    ParentFunctionName = functionNameTxt.Text,
                    SonFunctionName = x.SonFunctionName,
                    Orderby = x.Orderby
                }).ToArray();
        }

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

            return true;
        }

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

                Reset();

                data = securityFunctionRequest.FindByKey(functionNameSearchTxt.Text);

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

                    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 SecurityFunctionData();
            securityFunctionEntity = new SecurityFunctionDisplayData()
            {
                CreatedBy = string.Empty,
                UpdatedBy = string.Empty,
                CreatedDatetime = DateTime.Now,
                UpdatedDatetime = DateTime.Now,
            };
            data.SecurityFunction = securityFunctionEntity;

            PackEntityToUI();

            functionNameTxt.Focus();
        }

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

            SetDisplayMode();
        }

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

            dataGv.SetDataSource(data.SecurityFunctionMapParents);
            dataSonGv.SetDataSource(data.SecurityFunctionMapSons);
        }

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

            securityFunctionEntity = null;

            guiOperateHelper.ResetControls(this.contentPanel);

            SetDisplayMode();

            functionNameSearchTxt.Focus();
        }

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

        }


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

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

                functionNameSearchTxt.Text = ((SecurityFunctionEntity[])dialog.OutputData)[0].FunctionName;

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

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

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

                permissionNameTxt.Text = ((SecurityPermissionEntity[])dialog.OutputData)[0].PermissionName;
            }
            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(functionNameSearchTxt.Text))
                {
                    ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_VALID_INPUT, GuiOperateHelper.GetLabelText(functionNameSearchLabel.Text)));
                    this.functionNameSearchTxt.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 (securityFunctionEntity == 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;

                securityFunctionRequest.Delete(securityFunctionEntity.FunctionName);

                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)
                    securityFunctionRequest.Insert(data);
                else
                    securityFunctionRequest.Update(data);


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

                functionNameSearchTxt.Text = securityFunctionEntity.FunctionName;
                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 addBut_Click(object sender, EventArgs e)
        {
            try
            {
                AbstractForm dialog = GetAbstractDialog(typeof(SecurityFunctionEnquiryPage).Name);

                SecurityFunctionSearchCriteria criteria = new SecurityFunctionSearchCriteria();
                criteria.FunctionIndc = YesNoPolicy.NO;
                criteria.FunctionIndcEnable = false;
                if (DialogResult.OK != dialog.ShowViewDialog(null, criteria)) return;

                SecurityFunctionEntity[] securityFunctions = (SecurityFunctionEntity[])dialog.OutputData;
                SecurityFunctionMapViewEntity map;
                List<SecurityFunctionMapViewEntity> l = new List<SecurityFunctionMapViewEntity>();

                List<string> parentFunctionNames = new List<string>();

                int maxOrder = 1;
                if (dataSonGv.Rows.Count > 1)
                {
                    maxOrder = dataSonGv.GetAllRows<SecurityFunctionMapViewEntity>().Max(x => x.Orderby) + 1;
                    parentFunctionNames = dataSonGv.GetAllRows<SecurityFunctionMapViewEntity>().Select(x => x.ParentFunctionName).ToList();
                }

                foreach (SecurityFunctionEntity securityFunction in securityFunctions)
                {
                    if (parentFunctionNames.Contains(securityFunction.FunctionName)) continue;
                    parentFunctionNames.Add(securityFunction.FunctionName);

                    map = new SecurityFunctionMapViewEntity();
                    map.ParentFunctionName = securityFunction.FunctionName;
                    map.ParentFunctionLocalName = securityFunction.FunctionLocalName;
                    map.Orderby = maxOrder++;

                    l.Add(map);
                }

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

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

            dataGv.DeleteRows(dataGv.SelectedCells);
        }

        private void addSonBut_Click(object sender, EventArgs e)
        {
            try
            {
                if (functionIndcCombo.GetValue() != YesNoPolicy.NO)
                {
                    ShowMessageBox.ShowInfo(securityMessagePolicy.ComposeMessage(SecurityMessagePolicy.GUI_VALID_SELECT, GuiOperateHelper.GetLabelText(functionIndcLabel.Text)));
                    functionIndcCombo.Focus();
                    return;
                }

                AbstractForm dialog = GetAbstractDialog(typeof(SecurityFunctionEnquiryPage).Name);

                SecurityFunctionSearchCriteria criteria = new SecurityFunctionSearchCriteria();
                criteria.FunctionIndc = YesNoPolicy.YES;
                criteria.FunctionIndcEnable = false;
                if (DialogResult.OK != dialog.ShowViewDialog(null, criteria)) return;

                SecurityFunctionEntity[] securityFunctions = (SecurityFunctionEntity[])dialog.OutputData;
                SecurityFunctionMapViewEntity map;
                List<SecurityFunctionMapViewEntity> l = new List<SecurityFunctionMapViewEntity>();

                List<string> sonFunctionNames = new List<string>();

                int maxOrder = 1;
                if (dataSonGv.Rows.Count > 1)
                {
                    maxOrder = dataSonGv.GetAllRows<SecurityFunctionMapViewEntity>().Max(x => x.Orderby) + 1;
                    sonFunctionNames = dataSonGv.GetAllRows<SecurityFunctionMapViewEntity>().Select(x => x.SonFunctionName).ToList();
                }
                foreach (SecurityFunctionEntity securityFunction in securityFunctions)
                {
                    if (sonFunctionNames.Contains(securityFunction.FunctionName)) continue;
                    sonFunctionNames.Add(securityFunction.FunctionName);

                    map = new SecurityFunctionMapViewEntity();
                    map.SonFunctionName = securityFunction.FunctionName;
                    map.SonFunctionLocalName = securityFunction.FunctionLocalName;
                    map.Orderby = maxOrder++;

                    l.Add(map);
                }

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

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

            dataSonGv.DeleteRows(dataSonGv.SelectedCells);
        }
    }
}
