using CloudBuilder.Core.DependencyInjection.Form;
using CloudBuilder.Core.DependencyInjection.Request;
using CloudBuilder.Core.Service;
using CloudBuilder.Gui.DependencyInjection;
using CloudBuilder.Request.Security;
using CloudBuilder.Security.Entity;
using CloudBuilder.Security.Policy;
using CloudBuilder.Security.Utility;
using Krypton.Navigator;
using Krypton.Toolkit;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CloudBuilder.Gui
{
    public partial class AbstractForm : KryptonForm, IForm
    {
        private LoginContextPermission loginContextPermission;
        private SecurityMessagePolicy securityMessagePolicy;
        public string SecurityUserId = string.Empty;
        public IContext Context;
        //public WCFContract Wcf = null;
        private object activatedParam;
        public bool IsDialog = false;
        public object OutputData = null;
        public object InputData = null;

        public string ParentFunctionId { get; set; }
        public string FunctionId { get; set; }
        public object ActivatedParam { get; set; }

        protected GuiBindingContext guiBindingContext;
        protected GuiOperateHelper guiOperateHelper = null;

        public KryptonNavigator KryptonNavigator { get; set; }
        public Dictionary<string, KryptonPage> PageContext = new Dictionary<string, KryptonPage>();
        public GuiDisplayMode DisplayMode;

        public AbstractForm()
        {
            InitializeComponent();
        }


        public AbstractForm(object param)
            : this()
        {
            activatedParam = param;
        }

        public virtual void FunctionActivated(object param)
        {

        }

        public virtual void FunctionLoaded()
        {
            DisplayMode = GuiDisplayMode.View;

            InitResourceManager();
        }

        public string GetTitle(string functionName)
        {
            try
            {
                IContext loginContext = ServiceHelper.GetInterfaceService<IContext>()!;
                SecurityFunctionRequest securityFunctionRequest = ServiceHelper.GetTypeService<SecurityFunctionRequest>();
                SecurityFunctionEntity function = securityFunctionRequest.FindByFunctionName(functionName);
                if (function == null) return null;
                return loginContext.GetCulture() == LoginContext.CULTURE_EN ? function.FunctionEngName : function.FunctionLocalName;
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
                return null;
            }
        }

        public void InitResourceManager()
        {
            IContext loginContext = ServiceHelper.GetInterfaceService<IContext>()!;
            string typeName = this.GetType().FullName + "_" + loginContext.GetCulture();
            if (Assembly.GetAssembly(this.GetType()).GetManifestResourceNames().Contains(typeName + ".resources"))
            {
                ResourceManager rm = new ResourceManager(typeName, Assembly.GetAssembly(this.GetType()));

                GuiOperateHelper.SetControlsText(this, rm);
            }
        }

        public AbstractForm GetAbstractDialog(string functionViewId)
        {
            return GetAbstractDialog(functionViewId, null);
        }

        public AbstractForm GetAbstractDialog(string functionViewId, object param)
        {
            //if (ctx == null) ctx = ContextRegistry.GetContext();

            //AbstractForm v = (AbstractForm)ctx.CreateObject(functionViewId, null, null);
            AbstractForm v = new AbstractForm();
            //v.Wcf = new WCFContract();

            v.IsDialog = true;

            v.FunctionId = functionViewId;

            v.ActivatedParam = param;

            v.FunctionLoaded();

            v.FunctionActivated(param);

            v.StartPosition = FormStartPosition.CenterScreen;

            InitResourceManager();

            return v;
        }

        public AbstractPage GetAbstractPage()
        {
            foreach (Control c in this.Controls)
            {
                if (c is AbstractPage)
                {
                    return (AbstractPage)c;
                }
            }
            return null;
        }

        public KryptonPage GetAbstractPage(ToolStripMenuItem sender)
        {
            KryptonPage af = GetAbstractPage(sender.Name);
            af.Text = sender.Text;

            return af;
        }

        public KryptonPage GetAbstractPage(string functionViewId)
        {
            return GetAbstractPage(functionViewId, null);
        }

        private KryptonPage GetAbstractPage(string functionViewId, object param)
        {
            loginContextPermission = new LoginContextPermission();
            IContext loginContext = ServiceHelper.GetInterfaceService<IContext>()!;
            if (!loginContext.Assert(loginContextPermission.AssertByFunctionName, functionViewId))
            {
                securityMessagePolicy = ServiceHelper.GetTypeService<SecurityMessagePolicy>()!;
                throw new ValidationException(securityMessagePolicy.ComposeMessage("no_permission"));
            }

            KryptonPage v;
            if (!PageContext.Keys.Contains(functionViewId))
            {
                v = new KryptonPage();
                AbstractPage page = ServiceHelper.GetBaseTypeService<AbstractPage>(functionViewId);
                page.Dock = DockStyle.Fill;
                page.ActivatedParam = param;
                page.InitResourceManager();
                page.ParentKryptonPage = v;
                page.ParentAbstractForm = this;
                v.Controls.Add(page);

                v.Text = GetTitle(functionViewId);
            }
            else
            {
                v = PageContext[functionViewId];
            }

            return v;
        }

        public KryptonPage GetInitPage(string functionViewId, KryptonNavigator kryptonNavigator, string title, object param)
        {
            KryptonPage v;
            AbstractPage abstractPage = null; ;
            if (!PageContext.Keys.Contains(functionViewId))
            {
                v = new KryptonPage();
                abstractPage = ServiceHelper.GetBaseTypeService<AbstractPage>(functionViewId);
                abstractPage.Dock = DockStyle.Fill;
                abstractPage.ActivatedParam = param;
                abstractPage.InitResourceManager();
                abstractPage.ParentAbstractForm = this;

                v.Controls.Add(abstractPage);

                v.Text = title;
            }
            else
            {
                v = PageContext[functionViewId];

                foreach (Control c in v.Controls)
                {
                    if (c is AbstractPage)
                    {
                        abstractPage = (AbstractPage)c;
                        break;
                    }
                }

            }

            v.Text = title;

            abstractPage.FunctionId = functionViewId;

            abstractPage.KryptonNavigator = kryptonNavigator;

            abstractPage.ActivatedParam = param;

            abstractPage.FunctionLoaded();

            abstractPage.FunctionActivated(param);

            InitResourceManager();

            return v;
        }

        public void DisplayAbstractPage(ToolStripMenuItem sender, KryptonNavigator kryptonNavigator)
        {
            DisplayAbstractPage(sender.Name, sender.Text, null, kryptonNavigator);
        }

        public void DisplayAbstractPage(string functionViewId)
        {
            DisplayAbstractPage(functionViewId, null);
        }

        public void DisplayAbstractPage(string functionViewId, string title, object param, KryptonNavigator kryptonNavigator)
        {
            //deselecting page1,selecting page 2,deselected page1,selected page2,selectedpagechanged page2
            ////如果没有权限返回
            KryptonPage af = GetAbstractPage(functionViewId, param);
            AbstractPage page = null;
            foreach (Control c in af.Controls)
            {
                if (c is AbstractPage)
                {
                    page = (AbstractPage)c;
                    break;
                }
            }

            if (!string.IsNullOrEmpty(title))
            {
                af.Text = title;
            }
            else
            {
                af.Text = GetTitle(functionViewId);
            }

            if (!PageContext.Keys.Contains(functionViewId))
            {
                page.FunctionLoaded();

                kryptonNavigator.Pages.Add(af);

                PageContext.Add(functionViewId, af);
            }

            if (page == null) return;

            page.KryptonNavigator = kryptonNavigator;

            af.Visible = true;
            kryptonNavigator.SelectedPage = af;

            kryptonNavigator.Focus();

            kryptonNavigator.SelectedPage.Focus();

            page.FunctionActivated(param);
        }

        public void DisplayAbstractPage(string functionViewId, string title, object param)
        {
            DisplayAbstractPage(functionViewId, title, param, this.KryptonNavigator);
        }

        public void DisplayAbstractPage(string functionViewId, string title)
        {
            DisplayAbstractPage(functionViewId, title, null, this.KryptonNavigator);
        }

        public virtual KryptonNavigator GetKryptonNavigator()
        {
            return null;
        }

        public virtual void Print()
        {

        }

        public static void SetMid(Form form)
        {
            // Center the Form on the user's screen everytime it requires a Layout.
            form.SetBounds((Screen.GetBounds(form).Width / 2) - (form.Width / 2),
                (Screen.GetBounds(form).Height / 2) - (form.Height / 2),
                form.Width, form.Height, BoundsSpecified.Location);
        }

        public DialogResult ShowFormDialog()
        {
            return this.ShowFormDialog(null, false);
        }

        public DialogResult ShowFormDialog(string title)
        {
            return this.ShowFormDialog(title, false);
        }

        public DialogResult ShowFormDialog(string title, bool topMost)
        {
            IsDialog = true;

            if (!string.IsNullOrEmpty(title))
                this.Text = title;

            this.TopMost = topMost;

            this.ShowDialog();

            return DialogResult;
        }
        public virtual DialogResult ShowDialog(object inputData)
        {
            return ShowDialog(null, inputData);
        }

        public virtual DialogResult ShowDialog(string title, object inputData)
        {
            this.InputData = inputData;

            return this.ShowFormDialog(title);
        }

        public virtual DialogResult ShowViewDialog(object inputData)
        {
            return ShowViewDialog(null, inputData);
        }

        public virtual DialogResult ShowViewDialog(string title, object inputData)
        {
            this.InputData = inputData;
            this.GetAbstractPage().InitInputData(inputData, GuiDisplayMode.View);

            DialogResult dr = this.ShowFormDialog(title);
            if (DialogResult.OK != dr) return dr;
            if (this.OutputData == null)
                this.OutputData = this.GetAbstractPage().GetOutputData();

            return dr;
        }

        public virtual DialogResult ShowCreateDialog()
        {
            return ShowCreateDialog(null);
        }

        public virtual DialogResult ShowCreateDialog(string title)
        {
            this.GetAbstractPage().InitInputData(null, GuiDisplayMode.Create);

            DialogResult dr = this.ShowFormDialog(title);
            if (DialogResult.OK != dr) return dr;

            if (this.OutputData == null)
                this.OutputData = this.GetAbstractPage().GetOutputData();

            return dr;
        }

        public virtual DialogResult ShowCreateDialog(string title, object inputData)
        {
            this.InputData = inputData;

            this.GetAbstractPage().InitInputData(inputData, GuiDisplayMode.Create);

            DialogResult dr = this.ShowFormDialog(title);
            if (DialogResult.OK != dr) return dr;

            if (this.OutputData == null)
                this.OutputData = this.GetAbstractPage().GetOutputData();

            return dr;
        }

        public virtual DialogResult ShowAmendDialog(object inputData)
        {
            return ShowAmendDialog(null, inputData);
        }

        public virtual DialogResult ShowAmendDialog(string title, object inputData)
        {
            this.InputData = inputData;
            this.GetAbstractPage().InitInputData(inputData, GuiDisplayMode.Amend);
            DialogResult dr = this.ShowFormDialog(title);
            if (DialogResult.OK != dr) return dr;

            if (this.OutputData == null)
                this.OutputData = this.GetAbstractPage().GetOutputData();

            return dr;
        }

        public new void Show()
        {
            Show(null);
        }

        public void Show(string title)
        {
            IsDialog = true;

            this.Text = title;

            this.ShowFormDialog();
        }

        /// <summary>
        ///  元参数传入HandleException(() => Save());
        /// </summary>
        /// <param name="action"></param>
        public void HandleException(Action action)
        {
            try
            {
                action();
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// 有参数传入
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="param"></param>
        public void HandleException<T>(Action<T> action, T param)
        {
            try
            {
                action(param);
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// 有参数传入，且有返回值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="R"></typeparam>
        /// <param name="action"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public R HandleException<T, R>(Func<T, R> action, T param)
        {
            try
            {
                return action(param);
            }
            catch (ValidatedException ex)
            {
                ShowMessageBox.ShowInfo(ex.Message);
            }
            catch (ServiceErrorException ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }
            catch (Exception ex)
            {
                ShowMessageBox.ShowError(ex.Message);
            }

            return default(R)!;
        }
    }
}


