using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.IO;

namespace Mesnac.Basic
{
    /// <summary>
    /// 组态工程运行配置解析类
    /// </summary>
    public class RunSchema
    {
        #region 定义变量

        private string _projectPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(typeof(RunSchema).Assembly.CodeBase).Replace("file:\\", String.Empty), "Data", "MCProject");            //组态工程路径
        private string _eventConfigPath = String.Empty;        //事件处理(Action)配置文件路径
        private string _runSchemaFilePath = "RunSchema.xml";   //运行结构配置文件路径

        private Dictionary<string, string> _runSchemaDic = new Dictionary<string, string>();

        #endregion

        #region 定义属性

        public Dictionary<string, string> RunSchemaDic
        {
            get
            {
                if (_runSchemaDic.Count == 0)
                {
                    ParseFromRunSchema();
                }
                return _runSchemaDic;
            }
            private set
            {
                _runSchemaDic = value;
            }
        }
        /// <summary>
        /// 组态工程路径
        /// </summary>
        public string ProjectPath
        {
            get { return this._projectPath; }
            set { this._projectPath = value; }
        }

        /// <summary>
        /// 事件处理(Action)配置文件路径
        /// </summary>
        public string EventConfigPath
        {
            get { return this._eventConfigPath; }
            set { this._eventConfigPath = value; }
        }

        #endregion

        #region 单例模式实现

        private static RunSchema _this;     //私有静态实例,保存全局作用域中的唯一实例

        /// <summary>
        /// 静态实例属性
        /// </summary>
        public static RunSchema Instance
        {
            get
            {
                if (null == _this)
                    _this = new RunSchema();
                return _this;
            }
        }

        /// <summary>
        /// 私有构造方法
        /// </summary>
        private RunSchema()
        {
            this._runSchemaDic = new Dictionary<string, string>();
        }

        #endregion

        #region 基本信息
        public string FilePath()
        {
            return Path.Combine(this._projectPath, this._runSchemaFilePath);
        }
        #endregion

        #region 检测配置文件是否存在
        /// <summary>
        /// 检测配置文件是否存在(先检测组态工程目录,在检测事件处理(Action)配置文件路径)
        /// </summary>
        /// <returns>存在返回true,否则返回false</returns>
        public bool Exists()
        {
            string runSchemaFile = FilePath();
            string runSchemaFile2 = Path.Combine(this._eventConfigPath, this._runSchemaFilePath);
            if (File.Exists(runSchemaFile) || File.Exists(runSchemaFile2))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region 解析运行环境主配置文件RunSchema.xml
        /// <summary>
        /// 解析运行环境主配置文件RunSchema.xml
        /// </summary>
        public void ParseFromRunSchema()
        {
            try
            {
                //如果组态工程目录(MCProject)下有RunSchema文件,则首先以组态工程目录下的文件为配置文件,
                //否则以事件处理(Action)配置文件所在的目录下的RunSchema文件为准
                string runSchemaFile = FilePath();
                Dictionary<string, string> dic = new Dictionary<string, string>();
                if (!File.Exists(runSchemaFile))
                {
                    runSchemaFile = Path.Combine(this._eventConfigPath, this._runSchemaFilePath);
                }
                if (File.Exists(runSchemaFile))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(runSchemaFile);
                    XmlNodeList nodeList = doc.GetElementsByTagName("add");
                    foreach (XmlNode node in nodeList)
                    {
                        string key = node.Attributes["key"].Value;
                        if (!dic.ContainsKey(key))
                        {
                            string value = node.Attributes["value"].Value;
                            dic.Add(key, value);
                        }
                        else
                        {
                            //存在重复键
                            ICSharpCode.Core.LoggingService<RunSchema>.Error("配置文件中存在重复键的配置项,key = " + key);
                        }
                    }
                }
                else
                {
                    //配置文件不存在
                    ICSharpCode.Core.LoggingService<RunSchema>.Warn("应用程序配置文件不存在!");
                }
                this._runSchemaDic = dic;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<RunSchema>.Error(ex.Message);
                throw ex;
            }
        }
        /// <summary>
        /// 保存配置信息
        /// </summary>
        /// <param name="dic"></param>
        /// <param name="runSchemaFile"></param>
        public void UpdateToRunSchema(Dictionary<string, string> dic)
        {
            string runSchemaFile = FilePath();
            if (dic != null && dic.Count > 0)
            {
                XmlDocument doc = new XmlDocument();
                XmlElement root = doc.CreateElement("configuration");
                foreach (string key in dic.Keys)
                {
                    XmlElement eAdd = doc.CreateElement("add");
                    XmlAttribute eAttKey = doc.CreateAttribute("key");
                    eAttKey.Value = key;
                    XmlAttribute eAttValue = doc.CreateAttribute("value");
                    eAttValue.Value = dic[key];
                    eAdd.Attributes.Append(eAttKey);
                    eAdd.Attributes.Append(eAttValue);
                    root.AppendChild(eAdd);
                }
                doc.AppendChild(root);
                doc.Save(runSchemaFile);
            }
            ParseFromRunSchema();
        }
        /// <summary>
        /// 更新配置节点至文件
        /// </summary>
        /// <param name="key">要更新的配置项</param>
        /// <param name="newValue">要更新的配置项的值</param>
        public void UpdateNodeValueToRunSchema(string key, string newValue)
        {
            try
            {
                string runSchemaFile = FilePath();
                if (File.Exists(runSchemaFile))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(runSchemaFile);
                    XmlNodeList nodeList = doc.GetElementsByTagName("add");
                    bool flag = false;
                    foreach (XmlNode node in nodeList)
                    {
                        if (node.Attributes["key"].Value == key)
                        {
                            node.Attributes["value"].Value = newValue;
                            flag = true;
                            break;
                        }
                    }
                    if (!flag)
                    {
                        XmlElement eAdd = doc.CreateElement("add");
                        XmlAttribute eAttKey = doc.CreateAttribute("key");
                        eAttKey.Value = key;
                        XmlAttribute eAttValue = doc.CreateAttribute("value");
                        eAttValue.Value = newValue;
                        eAdd.Attributes.Append(eAttKey);
                        eAdd.Attributes.Append(eAttValue);
                        doc.DocumentElement.AppendChild(eAdd);
                    }
                    doc.Save(runSchemaFile);
                }
                else
                {
                    //配置文件不存在
                    ICSharpCode.Core.LoggingService<RunSchema>.Warn("应用程序配置文件不存在!");
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<RunSchema>.Error(ex.Message);
                throw ex;
            }
            ParseFromRunSchema();
        }

        #endregion

        #region 获取RunSchema配置文件中配置项的值
        /// <summary>
        /// 获取RunSchema配置文件中配置项的值
        /// </summary>
        /// <param name="key">配置型</param>
        /// <param name="defaultValue">获取不到时的默认值</param>
        /// <returns>返回对应配置项的值</returns>
        public string GetConfigValue(string key, string defaultValue)
        {
            string value = string.Empty;
            if (this.RunSchemaDic.TryGetValue(key, out value))
            {
                return value;
            }
            return defaultValue;
        }

        public bool GetConfigValue(string key, bool defaultValue)
        {
            string value = GetConfigValue(key, String.Empty);
            bool result = defaultValue;
            if (bool.TryParse(value, out result))
            {
                return result;
            }
            else
            {
                return defaultValue;
            }
        }

        public int GetConfigValue(string key, int defaultValue)
        {
            string value = GetConfigValue(key, String.Empty);
            int result = defaultValue;
            if (int.TryParse(value, out result))
            {
                return result;
            }
            else
            {
                return defaultValue;
            }
        }

        #endregion

        #region 判断Schema文件是否存在

        /// <summary>
        /// 判断Schema文件是否存在
        /// </summary>
        /// <returns>存在返回true,失败返回false</returns>
        public bool IsSchemaExists()
        {
            string runSchemaFile = FilePath();
            if (File.Exists(runSchemaFile))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion
    }
}