using System;
using System.Text;

namespace Wayne.Lib.Log
{
    /// <summary>
    /// An generic entry to be logged containing details regarding what to log,
    /// the datetime and who was performing the logging etc.
    /// 
    /// This class is inherited by DebugLogEntry, EventLogEntry and ErrorLogEntry
    /// which adds on more specific properties.
    /// </summary>
    public class LogEntry
    {
        #region Fields

        private readonly EntityCategory entityCategory;
        private readonly DateTime dateTime;
        private readonly UInt64 logEntryIndex;
        private readonly object logObject;

        private static DateTime startDateTime = DateTime.Now;
        private static readonly int StartTick = Environment.TickCount;

        #endregion

        #region Constructors

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="entity">The entity that performed the logging.</param>
        /// <param name="logObject">The object to log.</param>
        internal LogEntry(IIdentifiableEntity entity, object logObject)
            : this(entity, logObject, string.Empty)
        {
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="entity">The entity that performed the logging.</param>
        /// <param name="logObject">The object to log.</param>
        /// <param name="category">The category of the log object.</param>
        internal LogEntry(IIdentifiableEntity entity, object logObject, object category)
        {
#if WindowsCE
            //since windows CE do not support milliseconds.
            //this is added so we can get a better understanding of performance
            //not exact and should probably be removed before production release
            dateTime = startDateTime.AddMilliseconds(Environment.TickCount - StartTick);
#else
            dateTime = DateTime.Now;
#endif
            //if (Logger.GlobalLogEntryCounter != null)
            //    logEntryIndex = Logger.GlobalLogEntryCounter.GetNextValue();

            this.logObject = logObject;

            //if (Logger.IsClosed || Logger.DebugConfig == null)
            //{
            //    entityCategory = new EntityCategory(entity, category);
            //}
            //else
            //{
            //    entityCategory = Logger.DebugConfig.GetEntityCategory(entity, category);
            //}
        }

        #endregion

        #region Properties

        /// <summary>
        /// The EntityCategory that performed the logging.
        /// </summary>
        public EntityCategory EntityCategory
        {
            get { return entityCategory; }
        }

        /// <summary>
        /// The object to log.
        /// </summary>
        public object LogObject
        {
            get { return logObject; }
        }

        /// <summary>
        /// The date time of the logging.
        /// </summary>
        public DateTime DateTime
        {
            get { return dateTime; }
        }

        #endregion

        #region Methods: AppendTextToStringBuilder

        /// <summary>
        /// Appends the object to log to a StringBuilder-output.
        /// </summary>
        /// <param name="logWriter">The logwriter to be used for logging.</param>
        /// <param name="output">The StringBuilder.</param>
        /// <param name="indentLength">The indent to be used if many lines.</param>
        /// <param name="isFirstLine">Is this the first line to log?</param>
        /// <param name="indent">A string holding a generated indent-text (=a number of spaces). Use AppendIndent() to append the indent.</param>
        internal virtual void AppendToStringBuilder(LogWriter logWriter, StringBuilder output,
            int indentLength, ref bool isFirstLine, ref string indent)
        {
            StringLogObject.AppendObjectToStringBuilder(logObject, output, logWriter, indentLength, ref isFirstLine, ref indent);
        }

        /// <summary>
        /// Returns the datetime as a string, using the given date time format.
        /// </summary>
        /// <param name="dateTimeFormat">The requested date time format.</param>
        /// <returns></returns>
        public string GetDateTimeString(string dateTimeFormat)
        {
            //return Logger.DateTimeToString(dateTime, dateTimeFormat, logEntryIndex);
            return "";
        }

        #endregion

        #region Debug methods

        /// <summary>
        /// Presents the class as a string.
        /// </summary>
        /// <returns></returns>
        public virtual string ToString(string format, IFormatProvider provider)
        {
            return string.Concat("LogEntry EntityCategory=", entityCategory, ", LogObject=", (logObject != null) ? logObject.ToString() : "null");
        }

        /// <summary>
        /// Presents the class as a string using the specified culture-specific format information.
        /// </summary>
        /// <returns></returns>
        public virtual string ToString(IFormatProvider provider)
        {
            return ToString(string.Empty, provider);
        }

        /// <summary>
        /// Presents the class as a string using a format string.
        /// </summary>
        /// <returns></returns>
        public virtual string ToString(string format)
        {
            return ToString(format, System.Globalization.CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// Presents the class as a string using a format string and the specified culture-specific format information.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return ToString(string.Empty, System.Globalization.CultureInfo.InvariantCulture);
        }

        #endregion
    }
}