using MultiLayout.UiModule;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Navigation;
using Unity;

namespace MultiLayout
{
    public class FlyLayoutManager : INotifyPropertyChanged
    {
        public static NavigationService NavigationService
        {
            get {
                return Application.Current.Properties["NavigationService"] as NavigationService;
            }
            set {
                Application.Current.Properties["NavigationService"] = value;
            }
        }



        NLog.ILogger logger = NLog.LogManager.GetCurrentClassLogger();
        /// <summary>
        /// 本地模块
        /// </summary>
        public List<IUiModule2> UIModules = new List<IUiModule2>();
        public IUnityContainer uiContainer;
        public IUnityContainer container;
        LoadingProgress lp;
        public FlyLayout layout;
        public List<string> serviceNames;
        List<IOnInit> onInits;


        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 当前被选中的设备
        /// </summary>
        public GageTabItem Selected { get; set; }

        /// <summary>
        /// 设备标签可见
        /// </summary>
        public bool IsGageTagVisible { get; set; } = true;
        public bool IsInOption { get; set; }
        public string GageTag
        {
            get {
                if (Selected != null)
                    return Selected.Title;
                else
                    return null;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public FlyLayoutManager()
        {
            
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="layout"></param>
        /// <param name="uiContainer"></param>
        /// <param name="serviceContainer"></param>
        public void Init(
            FlyLayout layout,
            IUnityContainer container,
            LoadingProgress lp
            )
        {
            //从根容器获取 UiModule 容器
            this.container = container;
            this.layout = layout;
            this.uiContainer = container.Resolve<IUnityContainer>("uiModule.ui");

            this.lp = lp;

            serviceNames = (from r in this.container.Registrations
                            where r.RegisteredType == typeof(IUnityContainer) 
                            && !string.IsNullOrEmpty(r.Name)
                            && Regex.IsMatch(r.Name, @"\w+\.service")
                            select r.Name).ToList();


            //找到所有的onInit
            onInits = new List<IOnInit>();
            onInits.AddRange(container.ResolveAll<IOnInit>());

            //找到所有的服务中的onInit
            foreach (var serviceName in serviceNames)
            {
                var serviceContainer = container.Resolve<IUnityContainer>(serviceName);
                var serviceOnInits = serviceContainer.ResolveAll<IOnInit>();
                foreach (var onInit in serviceOnInits)
                {
                    if (!onInits.Contains(onInit))
                    {
                        onInits.Add(onInit);
                    }
                }
            }
            onInits.Sort((o1, o2) =>
            {
                return o1.Level.CompareTo(o2.Level);
            });

        }

        /// <summary>
        /// 加载模块
        /// </summary>
        public async Task<Page> LoadModule()
        {
            //加载全部 ui module
            UIModules.AddRange(uiContainer.ResolveAll<IUiModule2>());
            await Task.Delay(10);
            lp.Progress += 10;


            //加载尺寸,位置
            int SH = (int)SystemParameters.WorkArea.Height;
            int SW = (int)SystemParameters.WorkArea.Width;

            int x = layout.Rect.X;
            if ((x < 0) || (x >= SW))
                x = 0;

            int y = layout.Rect.Y;
            if ((y < 0) || (y >= SH))
                y = 0;

            int w = layout.Rect.Width;
            if ((w < 100) || (w > SW))
                w = SW;

            int h = layout.Rect.Height;
            if ((h < 100)|| (h > SH))
                h = SH;

            Application.Current.MainWindow.Left = x;
            Application.Current.MainWindow.Top = y;
            Application.Current.MainWindow.Width = w;
            Application.Current.MainWindow.Height = h;
            Application.Current.MainWindow.WindowState = layout.WindowState;







            UserControl userControl;
            if (layout.GageTabItems == null || layout.GageTabItems.Count()==0)
            {
                //一个设备也没有,返回单设备界面!!!
                UcSingleGage ucSingleGage = new UcSingleGage();
                ucSingleGage.Init(this);
                userControl = ucSingleGage;
            }
            else if (layout.GageTabItems.Count() == 1)
            {
                //只有一个设备,返回单设备界面!!!
                userControl = await LoadModule_single();
            }
            else 
            {
                userControl = await LoadModule_multi();
            }
            Page pg = new Page();
            pg.Content = userControl;
            return pg;
        }



        async Task<UserControl> LoadModule_single() 
        {
            var gageTabItem = layout.GageTabItems.First();

           //获取容器
           IUnityContainer container = null;
            try
            {
                container = this.container.Resolve<IUnityContainer>(gageTabItem.ServiceContainerName);
            }
            catch (Exception e)
            {
                //失败了,那就不显示!!!!
                logger.Error(e, $"创建失败 gageTabItem({gageTabItem.Title})");
                //给它总容器
                container = this.container;
            }


            //把不支持的模块删除
            gageTabItem.Components.RemoveAll(c => !UIModules.Any(uiModule => c.Module == uiModule.GetType().FullName));

            //把布局内不存在于 Components 的删除
            gageTabItem.MenuItems.RemoveAll(id => !gageTabItem.Components.Any(c => c.ID == id));
            gageTabItem.DynAreaItems.RemoveAll(id => !gageTabItem.Components.Any(c => c.ID == id));
            foreach (var tabitem in gageTabItem.Items)
                tabitem.Graphs.RemoveAll(gc => !gageTabItem.Components.Any(c => c.ID == gc.ID));
            
            await Task.Delay(10);
            lp.Progress += 10;

            //创建页面
            UcSingleGage ucMainGage = new UcSingleGage();
            ucMainGage.Init(this);
            gageTabItem.TabControl = ucMainGage.tabControl_graph;

            //初始化每个区
            InitializeComponent_graph(gageTabItem, ucMainGage.tabControl_graph);
            await Task.Delay(10);
            lp.Progress += 10;

            InitializeComponent_dynarea(gageTabItem, ucMainGage.stackpanel_dynarea);
            await Task.Delay(10);
            lp.Progress += 10;

            InitializeComponent_menu(gageTabItem, ucMainGage.stackpanel_menu);
            await Task.Delay(10);
            lp.Progress += 10;

            return ucMainGage;
        }
        async Task<UserControl> LoadModule_multi() 
        {
            ucMultiGage = new UcMultiGage();
            ucMultiGage.Init(this);

            //注册导航器
            NavigationService = ucMultiGage.NavigationService;
            NavigationService.LoadCompleted += NavigationService_LoadCompleted;
            var tabControl_gage = ucMultiGage.TabControl;
            tabControl_gage.Items.Clear();

            foreach (var gageTabItem in layout.GageTabItems)
            {
                //获取容器
                IUnityContainer container = null;
                try
                {
                    container = this.container.Resolve<IUnityContainer>(gageTabItem.ServiceContainerName);

                }
                catch (Exception e)
                {
                    //失败了,使用总容器替换,不画了
                    logger.Error(e, $"创建失败 gageTabItem({gageTabItem.Title})");
                    continue;
                }

                //把不支持的模块删除
                gageTabItem.Components.RemoveAll(c => !UIModules.Any(uiModule => c.Module == uiModule.GetType().FullName));

                //把布局内不存在于 Components 的删除
                gageTabItem.MenuItems.RemoveAll(id => !gageTabItem.Components.Any(c => c.ID == id));
                gageTabItem.DynAreaItems.RemoveAll(id => !gageTabItem.Components.Any(c => c.ID == id));
                foreach (var tabitem in gageTabItem.Items)
                    tabitem.Graphs.RemoveAll(gc => !gageTabItem.Components.Any(c => c.ID == gc.ID));
                await Task.Delay(10);
                lp.Progress += 10;

                //创建页面
                TabItem tabItem = new TabItem();
                tabItem.Header = gageTabItem.Title;
                UcSingleGage ucMainGage = new UcSingleGage();
                ucMainGage.Init(this);
                tabItem.Content = ucMainGage;
                gageTabItem.TabControl = ucMainGage.tabControl_graph;
                //初始化每个区
                InitializeComponent_graph(gageTabItem, ucMainGage.tabControl_graph);
                await Task.Delay(10);
                lp.Progress += 10;
                InitializeComponent_dynarea(gageTabItem, ucMainGage.stackpanel_dynarea);
                await Task.Delay(10);
                lp.Progress += 10;
                InitializeComponent_menu(gageTabItem, ucMainGage.stackpanel_menu);
                await Task.Delay(10);
                lp.Progress += 10;

                tabControl_gage.Items.Add(tabItem);
            }

            TabControl_gage_SelectionChanged(tabControl_gage, null);
            tabControl_gage.SelectionChanged += TabControl_gage_SelectionChanged;

            return ucMultiGage;
        }


        public async Task OnPreInit() 
        {
            //运行全部onInit
            foreach (var onInit in onInits)
            {
                if (onInit.Level <= 0 )
                {
                    onInit.OnInit();
                    lp.Progress += 1;
                    await Task.Delay(2);
                }
            }
        }
        public async Task OnInit() 
        {
            //运行全部onInit
            foreach (var onInit in onInits) 
            {
                if (onInit.Level > 0)
                {
                    onInit.OnInit();
                    lp.Progress += 1;
                    await Task.Delay(2);
                }
            }
        }


        UcMultiGage ucMultiGage;
        private void NavigationService_LoadCompleted(object sender, NavigationEventArgs e)
        {
            if (ucMultiGage.InMainPage)
            {
                IsGageTagVisible = false;
            }
            else if (IsInOption)
            {
                IsGageTagVisible = false;
            }
            else 
            {
                IsGageTagVisible = true;
            }

        }

        private void TabControl_gage_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var tabControl_gage = sender as TabControl;
            if (tabControl_gage.SelectedIndex >= 0) 
            {
                if(tabControl_gage.SelectedIndex>=0 && tabControl_gage.SelectedIndex< layout.GageTabItems.Count())
                    Selected = layout.GageTabItems[tabControl_gage.SelectedIndex];
            }
        }

        void InitializeComponent_graph(GageTabItem gageTabItem, TabControl tabControl)
        {
            tabControl.Items.Clear();
            foreach (GraphTabItem item in gageTabItem.Items)
            {
                //grid
                Grid grid = new Grid();
                for (int i = 0; i < item.ColumnCount; i++)
                {
                    ColumnDefinition cd = new ColumnDefinition();
                    if (item.ColumnDefinitions.Count() > i)
                    {
                        if (item.ColumnDefinitions[i])
                            cd.Width = GridLength.Auto;
                    }
                    grid.ColumnDefinitions.Add(cd);
                }
                for (int i = 0; i < item.RowCount; i++)
                {
                    RowDefinition rd = new RowDefinition();
                    if (item.RowDefinitions.Count() > i)
                    {
                        if (item.RowDefinitions[i])
                            rd.Height = GridLength.Auto;
                    }
                    grid.RowDefinitions.Add(rd);
                }

                //graph
                foreach (GraphComponent gp in item.Graphs)
                {
                    var flyComponent = gageTabItem.Components.Find(c => c.ID == gp.ID);
                    var uiModule = GetUIModule(flyComponent.Module);

                    try
                    {
                        var container = this.container.Resolve<IUnityContainer>(flyComponent.ServiceContainerName);
                        
                        Frame frame = new Frame();
                        frame.SetValue(Frame.MarginProperty, new Thickness(2));
                        
                        frame.Content = uiModule.GetComponent(gp.ID, container);

                        frame.DataContext = gp;
                        frame.SetValue(Grid.ColumnProperty,gp.Rect.X);
                        frame.SetValue(Grid.RowProperty, gp.Rect.Y);
                        frame.SetValue(Grid.ColumnSpanProperty, gp.Rect.Width);
                        frame.SetValue(Grid.RowSpanProperty, gp.Rect.Height);
                        grid.Children.Add(frame);
                    }
                    catch(Exception e)
                    {
                        //失败了,那就不显示!!!!
                        logger.Error(e, $"创建失败 uiModule({flyComponent.Module})");
                    }
                    
                }
                TabItem tabitem = new TabItem()
                {
                    Header = item.Header
                };
                tabitem.Content = grid;
                tabControl.Items.Add(tabitem);
            }
        }

        void InitializeComponent_dynarea(GageTabItem gageTabItem, StackPanel stackpanel)
        {
            stackpanel.Children.Clear();
            foreach (var id in gageTabItem.DynAreaItems)
            {
                var flyComponent = gageTabItem.Components.Find(c => c.ID == id);
                var uiModule = GetUIModule(flyComponent.Module);

                
                try
                {
                    var container = this.container.Resolve<IUnityContainer>(flyComponent.ServiceContainerName);
                    Frame frame = new Frame();
                    frame.Content = uiModule.GetComponent(id, container);
                    stackpanel.Children.Add(frame);
                }
                catch (Exception e)
                {
                    //失败了,那就不显示!!!!
                    logger.Error(e, $"创建失败 uiModule({flyComponent.Module})");
                }
            }
        }
        void InitializeComponent_menu(GageTabItem gageTabItem, StackPanel stackpanel)
        {
            stackpanel.Children.Clear();
            foreach (var id in gageTabItem.MenuItems)
            {
                var flyComponent = gageTabItem.Components.Find(c => c.ID == id);
                var uiModule = GetUIModule(flyComponent.Module);


                try
                {
                    var container = this.container.Resolve<IUnityContainer>(flyComponent.ServiceContainerName);
                    Frame frame = new Frame();
                    frame.Content = uiModule.GetComponent(id, container);
                    stackpanel.Children.Add(frame);
                }
                catch (Exception e)
                {
                    //失败了,那就不显示!!!!
                    logger.Error(e, $"创建失败 uiModule({flyComponent.Module})");
                }
            }
        }

        IUiModule2 GetUIModule(string moduleName) 
        {
            return UIModules.Find(_uiModule => _uiModule.GetType().FullName == moduleName);
        }
        
        /// <summary>
        /// 通知全部模块,告诉它们现在正在使用的控件,保存多余的参数就删除。
        /// </summary>
        public void MatchParam()
        {
            var components = new List<FlyComponent>();
            foreach (var gageTabItem in layout.GageTabItems)
            {
                if(gageTabItem.Components!=null)
                    components.AddRange(gageTabItem.Components);
            }
            Dictionary<string, List<int>> modules = new Dictionary<string, List<int>>();
            foreach (var c in components)
            {
                if (modules.ContainsKey(c.Module))
                     modules[c.Module].Add(c.ID);
                else
                    modules.Add(c.Module, new List<int>(new int[] { c.ID }));
            }

            foreach (var m in modules)
            {
                var uiModule = GetUIModule(m.Key);
                if(uiModule!=null)//不应该有null,之前都删除了
                {
                    uiModule.MatchParam(m.Value.ToArray());
                }
                
            }
        }
    }
}