using System;
using System.Collections.Generic;
using System.Xml;

namespace Wayne.Lib.Log
{
    /// <summary>
    /// External logwriter output definition
    /// </summary>
    public class LogConfigExternalLogWriterOutput : LogConfigOutput
    {
        private string dateTimeFormat;

        /// <summary>
        /// Parameters as key/value pairs.
        /// </summary>
        public readonly Dictionary<string, string> Params = new Dictionary<string, string>();

        /// <summary>
        /// Log type of the external logger
        /// </summary>
        public string ExternalLogType { get; set; }

        /// <summary>
        /// Name of the external logger.
        /// </summary>
        public string ExternalLogName { get; set; }

        /// <summary>
        /// DateTime format to use
        /// </summary>
        public string DateTimeFormat
        {
            get { return dateTimeFormat; }
            set
            {
                dateTimeFormat = value;
                isDefaultDateTimeFormat = (dateTimeFormat == null);
                if (isDefaultDateTimeFormat)
                    dateTimeFormat = Logger.DefaultDateTimeFormat;
            }
        }

        /// <summary>
        /// How to log the entity 
        /// </summary>
        public EntityLogKind EntityLogKind { get; set; }

        /// <summary>
        /// Should the category be suppressed.
        /// </summary>
        public bool SuppressCategory { get; set; }
        private bool isDefaultDateTimeFormat;

        internal const string XmlType = "ExternalLogWriter";

        /// <summary>
        /// Constructor
        /// </summary>
        public LogConfigExternalLogWriterOutput()
        {
            DateTimeFormat = null; // To make it default date time format.
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="externalLogType"></param>
        /// <param name="externalLogName"></param>
        /// <param name="dateTimeFormat"></param>
        /// <param name="entityLogKind"></param>
        /// <param name="suppressCategory"></param>
        public LogConfigExternalLogWriterOutput(string externalLogType, string externalLogName, string dateTimeFormat, EntityLogKind entityLogKind, bool suppressCategory)
        {
            ExternalLogType = externalLogType;
            ExternalLogName = externalLogName;
            DateTimeFormat = dateTimeFormat;
            EntityLogKind = entityLogKind;
            SuppressCategory = suppressCategory;
        }

        /// <summary>
        /// Deserialization constructor
        /// </summary>
        /// <param name="parametersNode"></param>
        /// <param name="ns"></param>
        internal LogConfigExternalLogWriterOutput(XmlNode parametersNode, string ns)
        {
            XmlNode externalLogWriterParamsNode = parametersNode["ExternalLogWriterParams", ns];
            XmlAttribute externalLogTypeAttribute = externalLogWriterParamsNode.Attributes["ExternalLogType"];
            XmlAttribute externalLogNameAttribute = externalLogWriterParamsNode.Attributes["ExternalLogName"];

            ExternalLogType = externalLogTypeAttribute.Value;
            ExternalLogName = externalLogNameAttribute.Value;

            XmlAttribute dateTimeLogFormatAttribute = externalLogWriterParamsNode.Attributes["DateTimeLogFormat"];
            isDefaultDateTimeFormat = (dateTimeLogFormatAttribute == null);
            if (dateTimeLogFormatAttribute != null)
                DateTimeFormat = dateTimeLogFormatAttribute.Value;
            else
                DateTimeFormat = Logger.DefaultDateTimeFormat;

            XmlAttribute entityLogAttribute = externalLogWriterParamsNode.Attributes["EntityLog"];
            if (entityLogAttribute != null)
                EntityLogKind = (EntityLogKind)Enum.Parse(typeof(EntityLogKind), entityLogAttribute.Value, false);
            else
                EntityLogKind = EntityLogKind.Entity;

            XmlAttribute suppressCategoryAttribute = externalLogWriterParamsNode.Attributes["SuppressCategory"];
            if (suppressCategoryAttribute != null)
                SuppressCategory = XmlConvert.ToBoolean(suppressCategoryAttribute.Value);
            else
                SuppressCategory = false;
        }

        /// <summary>
        /// Serialization
        /// </summary>
        /// <param name="xmlWriter"></param>
        internal override void WriteXml(XmlWriter xmlWriter)
        {
            xmlWriter.WriteStartElement("Output");
            xmlWriter.WriteAttributeString("Type", XmlType);
            xmlWriter.WriteStartElement("Parameters");
            xmlWriter.WriteStartElement("ExternalLogWriterParams");

            xmlWriter.WriteAttributeString("ExternalLogType", ExternalLogType ?? string.Empty);
            xmlWriter.WriteAttributeString("ExternalLogName", ExternalLogName ?? string.Empty);
            if (!isDefaultDateTimeFormat)
                xmlWriter.WriteAttributeString("DateTimeLogFormat", DateTimeFormat ?? string.Empty);
            if (EntityLogKind != EntityLogKind.Entity)
                xmlWriter.WriteAttributeString("EntityLog", EntityLogKind.ToString());
            if (SuppressCategory)
                xmlWriter.WriteAttributeString("SuppressCategory", XmlConvert.ToString(SuppressCategory));

            foreach (KeyValuePair<string, string> valuePair in Params)
            {
                xmlWriter.WriteStartElement("Param");
                xmlWriter.WriteAttributeString("Id", valuePair.Key);
                xmlWriter.WriteString(valuePair.Value);
                xmlWriter.WriteEndElement(); // Param
            }

            xmlWriter.WriteEndElement(); // ExternalLogWriterParams
            xmlWriter.WriteEndElement(); // Parameters
            xmlWriter.WriteEndElement(); // Output
        }

        /// <summary>
        /// Clones the object
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new LogConfigExternalLogWriterOutput(ExternalLogType, ExternalLogName, DateTimeFormat, EntityLogKind, SuppressCategory);
        }
    }
}