using System;
using System.Xml;
namespace Wayne.Lib.Log
{
    /// <summary>
    /// Log config textfile output.
    /// </summary>
    public class LogConfigTextFileOutput : LogConfigOutput
    {
        private string filePath;
        private LogConfigTextFileMaxSize maxSize;

        /// <summary>
        /// Output file path
        /// </summary>
        public string FilePath
        {
            get { return filePath; }
            set
            {
                filePath = value;
                XmlDocument xmlDocument = new XmlDocument();
                string xml = string.Concat("<FilePath>", filePath, "</FilePath>");
                xmlDocument.LoadXml(xml);

                LogConfigTextFilePath = new LogConfigTextFilePath(xmlDocument.DocumentElement);
            }
        }

/// <summary>
/// Set to true to not add 3-line file closing/appending messages
/// Default is false, which does do the 3-line message
/// </summary>
        public bool ShortFileMessages { get; set; }

        /// <summary>
        /// Max size of the file
        /// </summary>
        public LogConfigTextFileMaxSize MaxSize
        {
            get { return maxSize; }
            set
            {
                if (value == null)
                    maxSize = new LogConfigTextFileMaxSize((long?)null);
                else
                    maxSize = value;
            }
        }

        /// <summary>
        /// Datetime format within the file
        /// </summary>
        public string DateTimeFormat { get; set; }

        /// <summary>
        /// Entity log kind
        /// </summary>
        public EntityLogKind EntityLogKind { get; set; }

        /// <summary>
        /// Should the category be suppressed within the log file
        /// </summary>
        public bool SuppressCategory { get; set; }

        /// <summary>
        /// Keep the file opened after writing the log entry
        /// </summary>
        public bool KeepFileOpened { get; set; }

        internal LogConfigTextFilePath LogConfigTextFilePath { get; private set; }

        internal const string XmlType = "TextFileLogWriter";

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="filePath">The path (incl xml nodes for dynamic data).</param>
        /// <param name="maxSize">The size limitations wanted. Null = no limits.</param>
        /// <param name="dateTimeFormat">The datetime format for each line. Null = default.</param>
        /// <param name="entityLogKind">The kind of entity line prefix to use.</param>
        /// <param name="suppressCategory">Should the log category be suppressed from the log?</param>
        public LogConfigTextFileOutput(string filePath, LogConfigTextFileMaxSize maxSize, string dateTimeFormat,
            EntityLogKind entityLogKind, bool suppressCategory)
            : this(filePath, maxSize, dateTimeFormat, entityLogKind, suppressCategory, true)
        {
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="filePath">The path (incl xml nodes for dynamic data).</param>
        /// <param name="maxSize">The size limitations wanted. Null = no limits.</param>
        /// <param name="dateTimeFormat">The datetime format for each line. Null = default.</param>
        /// <param name="entityLogKind">The kind of entity line prefix to use.</param>
        /// <param name="suppressCategory">Should the log category be suppressed from the log?</param>
        /// <param name="keepFileOpened">Should the file be kept open or closed after each write.</param>
        public LogConfigTextFileOutput(string filePath, LogConfigTextFileMaxSize maxSize, string dateTimeFormat,
            EntityLogKind entityLogKind, bool suppressCategory, bool keepFileOpened)
        {
            FilePath = filePath;
            MaxSize = maxSize;

            if (dateTimeFormat == null)
                DateTimeFormat = Logger.DefaultDateTimeFormat;
            else
                DateTimeFormat = dateTimeFormat;
            EntityLogKind = entityLogKind;
            SuppressCategory = suppressCategory;
            KeepFileOpened = keepFileOpened;
        }

        /// <summary>
        /// Deserialization constructor
        /// </summary>
        /// <param name="parametersNode"></param>
        /// <param name="ns"></param>
        internal LogConfigTextFileOutput(XmlNode parametersNode, string ns)
        {
            XmlNode textFileParamsNode = parametersNode["TextFileParams", ns];

            filePath = textFileParamsNode["FilePath", ns].InnerText;
            LogConfigTextFilePath = new LogConfigTextFilePath(textFileParamsNode["FilePath", ns]);

            MaxSize = new LogConfigTextFileMaxSize(textFileParamsNode["MaxSize", ns]);

            XmlNode dateTimeLogFormatNode = textFileParamsNode["DateTimeLogFormat", ns];
            if (dateTimeLogFormatNode != null)
                DateTimeFormat = dateTimeLogFormatNode.InnerText;
            else
                DateTimeFormat = Logger.DefaultDateTimeFormat;

            XmlNode entityLogNode = textFileParamsNode["EntityLog", ns];
            if (entityLogNode != null)
                EntityLogKind = (EntityLogKind)Enum.Parse(typeof(EntityLogKind), entityLogNode.InnerText, false);
            else
                EntityLogKind = EntityLogKind.Entity;

            XmlNode suppressCategoryNode = textFileParamsNode["SuppressCategory", ns];
            SuppressCategory = suppressCategoryNode != null && XmlConvert.ToBoolean(suppressCategoryNode.InnerText);

            XmlNode keepFileOpenedNode = textFileParamsNode["KeepFileOpened", ns];
            KeepFileOpened = keepFileOpenedNode == null || XmlConvert.ToBoolean(keepFileOpenedNode.InnerText);

            XmlNode shortFileMessagesNode = textFileParamsNode["ShortFileMessages", ns];
            if (shortFileMessagesNode == null)
            {
                ShortFileMessages = false;
            }
            else
            {
                ShortFileMessages = XmlConvert.ToBoolean(shortFileMessagesNode.InnerText);
            }


        }

        /// <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("TextFileParams");

            xmlWriter.WriteStartElement("FilePath");
            xmlWriter.WriteRaw(FilePath);
            xmlWriter.WriteEndElement(); // FilePath

            MaxSize.WriteXml(xmlWriter);

            xmlWriter.WriteElementString("DateTimeLogFormat", DateTimeFormat);
            if (EntityLogKind != EntityLogKind.Entity)
                xmlWriter.WriteElementString("EntityLog", EntityLogKind.ToString());
            if (SuppressCategory)
                xmlWriter.WriteElementString("SuppressCategory", XmlConvert.ToString(SuppressCategory));
            if (!KeepFileOpened)
                xmlWriter.WriteElementString("KeepFileOpened", XmlConvert.ToString(KeepFileOpened));

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

        /// <summary>
        /// Creates a clone of the object.
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new LogConfigTextFileOutput(FilePath, MaxSize, DateTimeFormat, EntityLogKind, SuppressCategory, KeepFileOpened);
        }
    }
}