using System;
using System.Collections.Generic;
using MECF.Framework.Common.OperationCenter;
using MECF.Framework.UI.Client.ClientBase;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.Command;

using System.Globalization;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.MECF.Framework.Common.SCCore;
using System.Linq;
using System.Windows.Media;
using Aitex.Core.RT.ConfigCenter;
using DocumentFormat.OpenXml.InkML;
using Aitex.Core.RT.OperationCenter;
using DocumentFormat.OpenXml.Spreadsheet;
using Color = System.Windows.Media.Color;
using Colors = System.Windows.Media.Colors;

namespace MECF.Framework.UI.Client.CenterViews.Configs.SystemConfig
{
    public class SystemConfigViewModel : UiViewModelBase, ISupportMultipleSystem
    {

        #region Properties

        private List<ConfigNode> _ConfigNodes = new List<ConfigNode>();
        public List<ConfigNode> ConfigNodes
        {
            get { return _ConfigNodes; }
            set { _ConfigNodes = value; NotifyOfPropertyChange("ConfigNodes"); }
        }

        private List<ConfigItem> _configItems = null;
        public List<ConfigItem> ConfigItems
        {
            get { return _configItems; }
            set
            {
                _configItems = value;
                NotifyOfPropertyChange("ConfigItems");
            }
        }

        string _CurrentNodeName = string.Empty;

        public BaseCommand<ConfigNode> TreeViewSelectedItemChangedCmd { private set; get; }


        private string _currentCriteria = String.Empty;
        public string CurrentCriteria
        {
            get { return _currentCriteria; }
            set
            {
                if (value == _currentCriteria)
                    return;

                _currentCriteria = value;
                NotifyOfPropertyChange("CurrentCriteria");
                ApplyFilter();
            }
        }

        private void ApplyFilter()
        {
            foreach (var node in ConfigNodes)
                node.ApplyCriteria(CurrentCriteria, new Stack<ConfigNode>());
        }

        private string _buttonText = "Show Changes";
        public string ButtonText
        {
            get { return _buttonText; }
            set
            {
                if (value == "Show All")
                    _buttonText = "Show All";
                else if (value == "Show Changes")
                    _buttonText = "Show Changes";

                NotifyOfPropertyChange("ButtonText");
            }
        }

        public int ChangesCount
        {
            get { return ((List<ConfigChangedInfo>)QueryDataClient.Instance.Service.GetConfig("SystemConfig.DataChangedList")).Count; }
            set
            {
                NotifyOfPropertyChange("ChangesCount");
            }
        }
        #endregion

        #region Functions
        public SystemConfigViewModel()
        {
            this.DisplayName = "System Config";
            TreeViewSelectedItemChangedCmd = new BaseCommand<ConfigNode>(TreeViewSelectedItemChanged);
        }

        protected override void OnInitialize()
        {
            base.OnInitialize();

            ConfigNodes = SystemConfigProvider.Instance.GetConfigTree(SystemName).SubNodes;
        }

        private void TreeViewSelectedItemChanged(ConfigNode node)
        {
            //_CurrentNodeName = string.IsNullOrEmpty(node.Path) ? node.Name : $"{node.Path}.{node.Name}";
            _CurrentNodeName = string.IsNullOrEmpty(node.Path) ? node.Name : node.Path;
            ConfigItems = node.Items;

            GetDataOfConfigItems();
        }

        private void GetDataOfConfigItems()
        {
            if (ConfigItems == null)
                return;

            List<ConfigChangedInfo> changes = (List<ConfigChangedInfo>)QueryDataClient.Instance.Service.GetConfig("SystemConfig.DataChangedList");

            for (int i = 0; i < ConfigItems.Count; i++)
            {
                string key = String.Format("{0}{1}{2}", _CurrentNodeName, ".", ConfigItems[i].Name);
                //获取当前值
                ConfigItems[i].CurrentValue = SystemConfigProvider.Instance.GetValueByName(SystemName, key);

                #region 赋值OldValue
                if (changes != null)
                {
                    bool isExist = false;
                    //改动项记录
                    foreach (var item in changes)
                    {
                        if (item.Name == key)
                        {
                            string s = item.OldValue;
                            if (ConfigItems[i].Type == DataType.Bool)
                            {
                                bool value;
                                if (bool.TryParse(s, out value))
                                {
                                    ConfigItems[i].OldValue = value ? "Yes" : "No";
                                }
                            }
                            else
                            {
                                try
                                {
                                    if (ConfigItems[i].Type == DataType.Int)
                                    {
                                        ConfigItems[i].OldValue = Convert.ToDouble(s).ToString("N0");

                                    }
                                    else if (ConfigItems[i].Type == DataType.Double)
                                    {
                                        ConfigItems[i].OldValue = Convert.ToDouble(s).ToString("N2");
                                    }
                                    else if (ConfigItems[i].Type == DataType.Color)
                                    {
                                        ConfigItems[i].OldValue = s;
                                    }
                                    else
                                    {
                                        ConfigItems[i].OldValue = s;
                                    }
                                }
                                catch
                                {
                                    //这部分应该不会运行到
                                    ConfigItems[i].OldValue = s;
                                }
                            }
                            isExist = true;
                            break;
                        }
                    }
                    //未改动则记录空白
                    if (!isExist)
                    {
                        ConfigItems[i].OldValue = "";
                    }
                }
                #endregion
                #region 赋值Value
                if (ConfigItems[i].Type == DataType.Bool)
                {
                    bool value;
                    if (bool.TryParse(ConfigItems[i].CurrentValue, out value))
                    {
                        ConfigItems[i].BoolValue = value;

                        ConfigItems[i].CurrentValue = value ? "Yes" : "No";
                    }
                }
                else if (ConfigItems[i].Type == DataType.Color)
                {
                    if (ColorConverter.ConvertFromString(ConfigItems[i].CurrentValue) is Color color)
                        ConfigItems[i].ColorValue = color;
                    else

                        ConfigItems[i].ColorValue = Colors.Transparent;
                }
                else
                {
                    try
                    {
                        if (ConfigItems[i].Type == DataType.Int)
                        {
                            ConfigItems[i].StringValue = Convert.ToDouble(ConfigItems[i].CurrentValue).ToString("N0");
                            //ConfigItems[i].StringValue = ConfigItems[i].CurrentValue;

                        }
                        else if (ConfigItems[i].Type == DataType.Double)
                        {
                            ConfigItems[i].StringValue = Convert.ToDouble(ConfigItems[i].CurrentValue).ToString("N2");
                        }
                        else
                        {
                            ConfigItems[i].StringValue = ConfigItems[i].CurrentValue;
                        }
                    }
                    catch
                    {
                        //这部分应该不会运行到
                        ConfigItems[i].StringValue = ConfigItems[i].CurrentValue;
                    }
                }
                #endregion
            }
        }

        /// <summary>
        /// 将千分位字符串转换成数字
        /// 说明：将诸如"–111,222,333的千分位"转换成-111222333数字
        /// 若转换失败则返回-1
        /// </summary>
        /// <param name="thousandthStr">需要转换的千分位</param>
        /// <returns>数字</returns>
        public int ParseThousandthStringInt(string thousandthStr)
        {

            if (!string.IsNullOrEmpty(thousandthStr))
            {

                try
                {
                    return int.Parse(thousandthStr, NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign);
                }
                catch (Exception ex)
                {
                    return -10000;
                    //Debug.WriteLine(string.Format("将千分位字符串{0}转换成数字异常，原因:{0}", thousandthStr, ex.Message));
                }
            }
            else
            {
                return -10000;
            }
        }
        public Double ParseThousandthStringDouble(string thousandthStr)
        {

            if (!string.IsNullOrEmpty(thousandthStr))
            {

                try
                {
                    return Double.Parse(thousandthStr, NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign);
                }
                catch (Exception ex)
                {
                    return -10000;
                    //Debug.WriteLine(string.Format("将千分位字符串{0}转换成数字异常，原因:{0}", thousandthStr, ex.Message));
                }
            }
            else
            {
                return -10000.0;
            }
        }

        public void SetValues(List<ConfigItem> items)
        {
            //key ：System.IsSimulatorMode 
            //value: true or false 都是字符串

            //input check
            foreach (var item in items)
            {

                string value;
                if (item.Type == DataType.Bool)
                {
                    value = item.BoolValue.ToString().ToLower();
                }
                else
                {
                    if (item.TextSaved && item.Tag != "ReadOnlySelection")
                        continue;

                    if (item.Type == DataType.Int)
                    {
                        int iValue;
                        int _iValue = ParseThousandthStringInt(item.StringValue);
                        if (_iValue <= -100000)
                        {
                            DialogBox.ShowWarning("The value should be Type Int .");
                            continue;
                        }
                        string sValue = _iValue.ToString();
                        if (int.TryParse(sValue, out iValue))
                        {
                            if (!double.IsNaN(item.Max) && !double.IsNaN(item.Min))
                            {
                                if (iValue > item.Max || iValue < item.Min)
                                {
                                    DialogBox.ShowWarning(string.Format("The value should be between {0}  and {1}.", ((int)item.Min).ToString(), ((int)item.Max).ToString()));
                                    continue;
                                }
                            }
                        }
                        else
                        {
                            DialogBox.ShowWarning("Please input valid data.");
                            continue;
                        }
                        //value = item.StringValue;
                        value = sValue;
                    }
                    else if (item.Type == DataType.Double)
                    {
                        double fValue;
                        double _iValue = ParseThousandthStringDouble(item.StringValue);
                        if (_iValue <= -100000)
                        {
                            DialogBox.ShowWarning("The value should be Type Double .");
                            continue;
                        }
                        string sValue = _iValue.ToString();
                        if (double.TryParse(sValue, out fValue))
                        {
                            if (!double.IsNaN(item.Max) && !double.IsNaN(item.Min))
                            {
                                if (fValue > item.Max || fValue < item.Min)
                                {
                                    DialogBox.ShowWarning(string.Format("The value should be between {0}  and {1}.", item.Min.ToString(), item.Max.ToString()));
                                    continue;
                                }

                                string[] box = fValue.ToString().Split('.');
                                if (box.Length > 1 && box[1].Length > 3)
                                {
                                    DialogBox.ShowWarning(string.Format("The value should be more than three decimal places"));
                                    continue;
                                }
                            }
                        }
                        else
                        {
                            DialogBox.ShowWarning("Please input valid data.");
                            continue;
                        }
                        //value = item.StringValue;
                        value = sValue;
                    }
                    else if (item.Type == DataType.Color)
                    {
                        value = item.ColorValue.ToString();
                    }
                    else
                        value = item.StringValue;
                }

                string key = String.Format("{0}{1}{2}", _CurrentNodeName, ".", item.Name);
                InvokeClient.Instance.Service.DoOperation($"{SystemName}.SetConfig", key, value);

                item.TextSaved = true;
            }

            Reload();
            //扩展Set触发其他事件
        }
        public void SetValue(ConfigItem item)
        {
            //key ：System.IsSimulatorMode 
            //value: true or false 都是字符串

            //input check
            string value;
            if (item.Type == DataType.Bool)
            {
                value = item.BoolValue.ToString().ToLower();
            }
            else
            {
                if (item.TextSaved && item.Tag != "ReadOnlySelection" && item.Type != DataType.Color)
                    return;

                if (item.Type == DataType.Int)
                {
                    int iValue;
                    int _iValue = ParseThousandthStringInt(item.StringValue);
                    if (_iValue <= -100000)
                    {
                        DialogBox.ShowWarning("The value should be Type Int .");
                        return;
                    }
                    string sValue = _iValue.ToString();
                    if (int.TryParse(sValue, out iValue))
                    {
                        if (!double.IsNaN(item.Max) && !double.IsNaN(item.Min))
                        {
                            if (iValue > item.Max || iValue < item.Min)
                            {
                                DialogBox.ShowWarning(string.Format("The value should be between {0}  and {1}.", ((int)item.Min).ToString(), ((int)item.Max).ToString()));
                                return;
                            }
                        }
                    }
                    else
                    {
                        DialogBox.ShowWarning("Please input valid data.");
                        return;
                    }
                    //value = item.StringValue;
                    value = sValue;
                }
                else if (item.Type == DataType.Double)
                {
                    double fValue;
                    double _iValue = ParseThousandthStringDouble(item.StringValue);
                    if (_iValue <= -100000)
                    {
                        DialogBox.ShowWarning("The value should be Type Double .");
                        return;
                    }
                    string sValue = _iValue.ToString();
                    if (double.TryParse(sValue, out fValue))
                    {
                        if (!double.IsNaN(item.Max) && !double.IsNaN(item.Min))
                        {
                            if (fValue > item.Max || fValue < item.Min)
                            {
                                DialogBox.ShowWarning(string.Format("The value should be between {0}  and {1}.", item.Min.ToString(), item.Max.ToString()));
                                return;
                            }

                            string[] box = fValue.ToString().Split('.');
                            if (box.Length > 1 && box[1].Length > 3)
                            {
                                DialogBox.ShowWarning(string.Format("The value should be more than three decimal places"));
                                return;
                            }
                        }
                    }
                    else
                    {
                        DialogBox.ShowWarning("Please input valid data.");
                        return;
                    }
                    //value = item.StringValue;
                    value = sValue;
                }
                else if (item.Type == DataType.Color)
                {
                    value = item.ColorValue.ToString();
                }
                else
                    value = item.StringValue;
            }

            string key = String.Format("{0}{1}{2}", _CurrentNodeName, ".", item.Name);
            InvokeClient.Instance.Service.DoOperation($"{SystemName}.SetConfig", key, value);

            item.TextSaved = true;

            Reload();

        }

        public void Reload()
        {
            GetDataOfConfigItems();
            ClearFilter();
            ChangesCount = 9999;
        }

        public void SaveAll()
        {
            if (ConfigItems == null)
                return;
            SetValues(ConfigItems);
            //ConfigItems.ForEach(item => SetValue(item));
        }

        public void CollapseAll()
        {
            SetExpand(ConfigNodes, false);
        }

        public void ExpandAll()
        {
            SetExpand(ConfigNodes, true);
        }

        public void ClearFilter()
        {
            CurrentCriteria = "";
        }

        public void SetExpand(List<ConfigNode> configs, bool expand)
        {
            if (configs == null)
                return;

            foreach (var configNode in configs)
            {
                configNode.IsExpanded = expand;

                if (configNode.SubNodes != null)
                    SetExpand(configNode.SubNodes, expand);
            }
        }

        public void ShowHideConfigs(List<ConfigNode> configs, bool isShow)
        {
            if (configs == null)
                return;

            foreach (var configNode in configs)
            {
                configNode.IsMatch = isShow;
                if (isShow)
                {
                    configNode.IsHighLight = false;
                }
                if (configNode.SubNodes != null)
                    ShowHideConfigs(configNode.SubNodes, isShow);
            }
        }

        public bool FindConfigNodeWithPath(ConfigNode node, string path, List<ConfigNode> matchnodes)
        {
            if (path.StartsWith(node.Path))     //该节点与路径重复
            {
                matchnodes.Add(node);       //暂时加入该节点
                if (path == node.Path)      //该节点与路径重复且相同
                {
                    node.IsHighLight = true;    //完全一致时高亮
                    return true;
                }
                else
                {
                    //该节点与路径重复但不相同
                    foreach (var item in node.SubNodes)
                    {
                        if (FindConfigNodeWithPath(item, path, matchnodes))
                        {
                            return true;
                        }
                    }
                    matchnodes.Remove(node);    //抛弃该节点
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 遍历所有配置节点，显示被修改过的节点，隐藏其他节点
        /// </summary>
        public void ShowChanges()
        {
            if (ButtonText == "Show Changes")
            {
                List<ConfigChangedInfo> changes = (List<ConfigChangedInfo>)QueryDataClient.Instance.Service.GetConfig("SystemConfig.DataChangedList");
                List<ConfigNode> temps = new List<ConfigNode>();
                if (changes != null && changes.Count != 0)
                {
                    //显示所有配置，取消高亮
                    ShowHideConfigs(ConfigNodes, true);

                    //筛选所有项，并高亮显示
                    foreach (var t in changes)
                    {
                        List<ConfigNode> nodes = new List<ConfigNode>();
                        foreach (var item in ConfigNodes)
                        {
                            if (FindConfigNodeWithPath(item, t.Name.Replace("." + t.Name.Split('.').Last(), ""), nodes))
                            {
                                temps.AddRange(nodes);
                                break;
                            }
                        }
                    }

                    //隐藏所有配置
                    ShowHideConfigs(ConfigNodes, false);

                    //显示被更改配置
                    foreach (var node in temps)
                    {
                        node.IsMatch = true;
                    }
                }

                ButtonText = "Show All";
            }
            else if (ButtonText == "Show All")
            {
                ShowHideConfigs(ConfigNodes, true);
                ButtonText = "Show Changes";
            }
            
        }

        /// <summary>
        /// 将所有变化过的项恢复原值（包括本次修改的值和上次软件修改的值）
        /// </summary>
        public void Revert2Last()
        {
            List<ConfigChangedInfo> s = (List<ConfigChangedInfo>)QueryDataClient.Instance.Service.GetConfig("SystemConfig.DataChangedList");
            if (s != null && s.Count > 0)
            {
                string tips = "";
                foreach (var t in s)
                {
                    var value = QueryDataClient.Instance.Service.GetConfig(t.Name);
                    if (value != null)
                    {
                        tips += t.Name + (t.Enable ? " " : " HAS ") + "CHANGED:\r\n(Previous)\t" + t.OldValue + " => " + value.ToString() + "\t(Latest)\r\n";
                    }
                }
                if (tips != "")
                {
                    if (DialogBox.Confirm("SystemConfig has Changed. Do you want to Revert-Those-Changes?\r\n"+tips))
                    {
                        InvokeClient.Instance.Service.DoOperation("SystemConfig.Revert");
                        Reload();
                        DialogBox.ShowInfo("Operated successfully.");
                    }
                }
            }
            

        }
        #endregion
    }
}
