using System;
using System.IO;
using System.Xml;
using System.Data;
using System.Data.Common;
using System.Configuration;
using System.Globalization;
using System.Collections.Specialized;
using System.Configuration.Provider;

namespace Winson.Framework.LogProviders
{
    /// <summary>
    /// 将日志写入XML文件
    /// </summary>
    partial class Log2XMLProvider : LogProviderBase
    {

        #region 属性
        private string _logpath;
        #endregion

        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("没有相关配置!");
            }

            if (String.IsNullOrEmpty(name))
            {
                name = "Log2XMLProvider";
            }

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "创建XML日志提供者");
            }

            base.Initialize(name, config);


            if (config["logPath"] == null)
            {
                // 默认日志文件路径
                config["logPath"] = @"Log\";
            }
            _logpath = config["logPath"];
            config.Remove("logPath");


            //如果有多余的属于，则抛出异常
            if (config.Count > 0)
            {
                string attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                    throw new ProviderException("未指定的属性: " + attr);
            }
        }

        public override bool OutputErrLog(string methodName, string parametersList, Exception exception)
        {
            string strFile = Utility.Utility.GetMapPath() + _logpath + String.Format("{0:yyyyMMdd}", DateTime.Today) + ".xml";

            if (!File.Exists(strFile))
                return CreateLog(strFile, methodName, parametersList, exception);
            else
                return AppendLog(strFile, methodName, parametersList, exception);

            return false;
        }


        #region 私有方法

        /// <summary>
        /// 创建日志文件
        /// </summary>
        /// <param name="logFile">日志文件</param>
        /// <param name="methodName">异常方法</param>
        /// <param name="parametersList">异常参数</param>
        /// <param name="exception">异常</param>
        /// <returns></returns>
        private bool CreateLog(string logFile, string methodName, string parametersList, Exception exception)
        {
            try
            {
                using (XmlTextWriter writer = new XmlTextWriter(logFile, System.Text.Encoding.UTF8))
                {
                    writer.Formatting = Formatting.Indented;
                    writer.Indentation = 4;
                    writer.WriteStartDocument(true);
                    writer.WriteStartElement("ErrorLog");
                    writer.WriteAttributeString("Date", String.Format("{0:yyyy-MM-dd}", DateTime.Today));

                    writer.WriteStartElement("ErrorTime");
                    writer.WriteAttributeString("Value", DateTime.Now.ToShortTimeString());


                    writer.WriteStartElement("Method");
                    writer.WriteValue(methodName);
                    writer.WriteEndElement();

                    writer.WriteStartElement("Parames");
                    writer.WriteValue(parametersList);
                    writer.WriteEndElement();

                    writer.WriteStartElement("ErrorMsg");
                    writer.WriteValue(exception.Message);
                    writer.WriteEndElement();

                    writer.WriteStartElement("Trace");
                    writer.WriteValue(exception.StackTrace);
                    writer.WriteEndElement();

                    writer.WriteEndElement();

                    writer.WriteEndElement();
                }
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }


        /// <summary>
        /// 追加到日志文件
        /// </summary>
        /// <param name="logFile">日志文件</param>
        /// <param name="methodName">异常方法</param>
        /// <param name="parametersList">异常参数</param>
        /// <param name="exception">异常</param>
        /// <returns></returns>
        private bool AppendLog(string logFile, string methodName, string parametersList, Exception exception)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                using (XmlTextReader reader = new XmlTextReader(logFile))
                {
                    doc.Load(reader);

                    XmlElement root = doc.DocumentElement;   //   获取根节点  


                    XmlElement eErrorDate = doc.CreateElement("ErrorTime");
                    XmlElement eFuncName = doc.CreateElement("Method");
                    XmlElement eParames = doc.CreateElement("Parames");
                    XmlElement eMsg = doc.CreateElement("ErrorMsg");
                    XmlElement eTrace = doc.CreateElement("Trace");

                    eErrorDate.SetAttribute("Value", DateTime.Now.ToShortTimeString());
                    eFuncName.InnerText = methodName;
                    eParames.InnerText = parametersList;
                    eMsg.InnerText = exception.Message;
                    eTrace.InnerText = exception.StackTrace;

                    eErrorDate.AppendChild(eFuncName);
                    eErrorDate.AppendChild(eParames);
                    eErrorDate.AppendChild(eMsg);
                    eErrorDate.AppendChild(eTrace);

                    root.AppendChild(eErrorDate);
                }
                doc.Save(logFile);
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }
        #endregion
    }
}
