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.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Resources;

namespace CloudBuilder.Gui
{
    public partial class AbstractPage : UserControl, IForm
    {
        public AbstractPage()
        {
            InitializeComponent();
        }

        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 AbstractForm ParentAbstractForm { get; set; }
        public KryptonPage ParentKryptonPage { 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 GuiDisplayMode DisplayMode;


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

        public virtual void FunctionActivated(object param)
        {

        }

        public virtual void FunctionSelected()
        {

        }

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

            InitResourceManager();
        }
        public virtual void Shown()
        {

        }

        public virtual bool FunctionDeactivating()
        {
            return true;
        }

        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)
        {
            AbstractForm v = new AbstractForm();

            AbstractPage page = ServiceHelper.GetBaseTypeService<AbstractPage>(functionViewId);
            v.Size = new Size(page.Size.Width + 28, page.Size.Height + 38);

            page.Dock = DockStyle.Fill;
            page.ActivatedParam = param;
            page.InitResourceManager();
            page.ParentAbstractForm = v;

            page.IsDialog = true;

            page.FunctionId = functionViewId;

            page.ActivatedParam = param;

            page.FunctionLoaded();

            page.FunctionActivated(param);
            page.AutoSize = true;
            page.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            page.BackColor = Color.White;

            page.FunctionSelected();

            v.Controls.Add(page);

            v.Text = GetTitle(functionViewId);
            v.AutoSize = true;
            v.StartPosition = FormStartPosition.CenterScreen;
            v.MaximizeBox = false;
            v.MinimizeBox = false;
            v.PaletteMode = PaletteMode.Office2010Silver;
            v.FormClosing += page.FormClosing;
            v.Shown += page.Shown;
            return v;
        }

        private void Shown(object sender,EventArgs e)
        {
            this.Showned();
        }

        public virtual void Showned()
        {

        }

        private void FormClosing(object sender, FormClosingEventArgs e)
        {
            this.FormClosing();
        }
        //窗口关闭时，自动释放内存
        public virtual void FormClosing()
        {
            var provider = ServiceHelper.GetService<BindingContextAttributeProvider>();
            provider.RemoveControlBinding(this.Controls);
        }

        public virtual void InitInputData(object param, GuiDisplayMode mode)
        {

        }

        public virtual object GetOutputData()
        {
            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 (!ParentAbstractForm.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 = ParentAbstractForm;
                v.Controls.Add(page);

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

            return v;
        }

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

                v.Controls.Add(page);

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

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

            }

            v.Text = title;

            page.FunctionId = functionViewId;

            page.KryptonNavigator = kryptonNavigator;

            page.ActivatedParam = param;

            page.FunctionLoaded();

            page.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);
            af.Visible = true;

            AbstractPage page = GetAbstractPage(af);


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

            if (!ParentAbstractForm.PageContext.Keys.Contains(functionViewId))
            {
                page.FunctionLoaded();
                page.ParentKryptonPage = af;

                kryptonNavigator.Pages.Add(af);

                ParentAbstractForm.PageContext.Add(functionViewId, af);
            }

            page.FunctionActivated(param);

            page.KryptonNavigator = kryptonNavigator;

            kryptonNavigator.SelectedPage = af;
        }

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

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

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

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

        public virtual KryptonNavigator GetKryptonNavigator()
        {
            return null;
        }

        public AbstractForm GetMainForm()
        {
            return ParentAbstractForm;
        }

        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 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);
            }
        }

        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);
            }
        }

        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)!;
        }
    }
}
