using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using log4net.Config;

namespace UEUserGuide
{
    /// <summary>
    /// This class provide the logging/tracing functionalities.
    /// </summary>
    public sealed class Logger
    {
        ///////////////////////////////////////////////////////////////////////
        #region Internal fields

        /// <summary>
        /// Logger component reference (log4net).
        /// </summary>
        private ILog _logger;

        #endregion Internal fields

        ///////////////////////////////////////////////////////////////////////
        #region Thread-safe Singleton implementation

        /// <summary>
        /// Unique instance of <seealso cref="FsComFramework.Logger.Logger"/>.
        /// </summary>
        private static volatile Logger instance = null;

        /// <summary>
        /// Synchronisation object.
        /// </summary>
        private static object _syncRoot = new Object();

        /// <summary>
        /// Internal ctor.
        /// </summary>
        private Logger()
        {
        }

        /// <summary>
        /// Instance accessor.
        /// </summary>
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// public GenericSAFrm()
        /// {
        ///     // Initialize logger.
        ///     Logger.Instance.Initialize("GenericSA");
        ///
        ///     InitializeComponent();
        /// }
        /// </code>
        /// </example>
        public static Logger Instance
        {
            get
            {
                lock (_syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Logger();
                    }

                    return instance;
                }
            }
        }

        #endregion Thread-safe Singleton implementation

        ///////////////////////////////////////////////////////////////////////
        #region Logger methods.

        /// <summary>
        /// Gets the Debug level status: true if set, false otherwise.
        /// </summary>
        public bool IsDebugLevelSet { get { return _logger.IsDebugEnabled; } }

        /// <summary>
        /// Gets the Info level status: true if set, false otherwise.
        /// </summary>
        public bool IsInfoLevelSet { get { return _logger.IsInfoEnabled; } }

        /// <summary>
        /// Gets the Warning level status: true if set, false otherwise.
        /// </summary>
        public bool IsWarningLevelSet { get { return _logger.IsWarnEnabled; } }

        /// <summary>
        /// Initialize the logger component.
        /// </summary>
        /// <param name="name">Logger name - see application configuation file, log4net XML element.</param>
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// public GenericSAFrm()
        /// {
        ///     // Initialize logger.
        ///     Logger.Instance.Initialize("GenericSA");
        ///
        ///     InitializeComponent();
        /// }
        /// </code>
        /// </example>
        public void Initialize(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                _logger = LogManager.GetLogger("TraceAppender");
                XmlConfigurator.Configure();
            }
            else
            {
                _logger = LogManager.GetLogger(name);
                XmlConfigurator.Configure();
            }
        }

        /// <summary>
        /// Log information message.
        /// </summary>
        /// <param name="fmt">Message format - <see>IFormater</see>.</param>
        /// <param name="args">List of argument to pass to the formater.</param>          
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// if (Logger.Instance.IsInfoLevelSet) Logger.Instance.InfoLogger("GenericSAFrm.Window_Loaded: All is ok, continue!");
        /// </code>
        /// </example>
        public void InfoLogger(string fmt, params object[] args)
        {
            if (_logger.IsInfoEnabled) _logger.InfoFormat(fmt, args);
        }

        /// <summary>
        /// Log warning message.
        /// </summary>
        /// <param name="fmt">Message format - <see>IFormater</see>.</param>
        /// <param name="args">List of argument to pass to the formater.</param>          
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// Logger.Instance.WarningLogger("GenericSAFrm.Window_Loaded: Configuration mismatch!");
        /// </code>
        /// </example>
        public void WarningLogger(string fmt, params object[] args)
        {
            if (_logger.IsWarnEnabled) _logger.WarnFormat(fmt, args);
        }

        /// <summary>
        /// Log error message.
        /// </summary>
        /// <param name="fmt">Message format - <see>IFormater</see>.</param>
        /// <param name="args">List of argument to pass to the formater.</param>          
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// Logger.Instance.ErrorLogger("GenericSAFrm.Window_Loaded: Wrong parameters.");
        /// </code>
        /// </example>
        public void ErrorLogger(string fmt, params object[] args)
        {
            if (_logger.IsErrorEnabled) _logger.ErrorFormat(fmt, args);
        }

        /// <summary>
        /// Log debug message.
        /// <remarks>Visible only if level in root XML element is set to ALL or DEBUG.</remarks>
        /// </summary>
        /// <param name="fmt">Message format - <see>IFormater</see>.</param>
        /// <param name="args">List of argument to pass to the formater.</param>          
        /// <example>
        /// The code below shows how to do Logger access:
        /// <code>
        /// if (Logger.Instance.IsDebugLevelSet) Logger.Instance.DebugLogger("GenericSAFrm.Window_Loaded: Parameters {0} is validated.", counter);
        /// </code>
        /// </example>
        public void DebugLogger(string fmt, params object[] args)
        {
            if (_logger.IsDebugEnabled) _logger.DebugFormat(fmt, args);
        }

        #endregion Logger methods.

        ///////////////////////////////////////////////////////////////////////
        #region Internal method helpers.

        #endregion Internal method helpers.
    }
}
