/*
|-------------------------------------------------------------------------------|
|	Copyright © Computer Ease Limited								            |
|	Address: 1/9 Bloack-A Lalmatia, Dhaka-1207, Bangladesh			            |
|	Email: info@celimited.com, cease@bol-online.com, web: www.celimited.com     |
|	Unauthorized copy or distribution is strictly prohibited		            |
|	Author: S. M. Russel,  Last modified date: 23/07/2012						|
|-------------------------------------------------------------------------------|
*/

using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using Ease.Core.Utility;
using System.Collections.Generic;

namespace Ease.Core.Utility
{
    #region Utility: Exception Log

    /// <summary>
    /// This object is used to log error raised in service.
    /// This class cannot be inherited.
    /// This class cannot be instantiated.
    /// All functions are static. 
    /// </summary>
    public sealed class ExceptionLog
    {
        private static string _mode;
        private static int _maxSize;
        private static int _maxFiles;
        private static string _source;
        private static object _syncObject = new object();

        static ExceptionLog()
        {
            AppConfigParser config = new AppConfigParser();

            string configvalue = ""; //#### ConfigUtility.GetAppSettings("exceptionHandler");
            if (!string.IsNullOrEmpty(configvalue))
                config.Parse(configvalue);

            //Mod of error
            _mode = "File";
            //if (config.Contains("mode"))
            //    _mode = config["mode"];

            //Source property
            _source = "Log";
            //if (config.Contains("source"))
            //    _source = config["source"];

            //No max of file in this folder
            _maxFiles = 10;
            //if (config.Contains("maxFiles"))
            //{
            //    try
            //    {
            //        _maxFiles = int.Parse(config["maxFiles"]);  //1 KB
            //    }
            //    catch { }
            //}

            //File size
            _maxSize = 5000 * 1024; //5 MB
            //if (config.Contains("maxFileSize"))
            //{
            //    try
            //    {
            //        _maxSize = int.Parse(config["maxFileSize"]) * 1024;     //1 KB
            //    }
            //    catch { }
            //}
        }

        private static void WriteToEventLog(string log)
        {
            try
            {
                //#### 
                EventLog.WriteEntry(_source, log, EventLogEntryType.Error);
            }
            catch
            {
                WriteToFile(log);
            }
        }

        private static void WriteToFile(string log)
        {
            string path = Path.Combine(Environment.CurrentDirectory, _source);
            string logFileSpec = Path.Combine(path, "Error.log");

            try
            {
                lock (_syncObject)
                {
                    if (!Directory.Exists(path))
                        Directory.CreateDirectory(path);

                    StreamWriter writer;
                    if (!File.Exists(logFileSpec))
                    {
                        writer = File.CreateText(logFileSpec);
                    }
                    else
                    {
                        FileInfo fi = new FileInfo(Path.Combine(path, logFileSpec));
                        if (fi.Length > _maxSize)
                        {
                            // Check no of files
                            ArrayList fileList = new ArrayList(Directory.GetFiles(path, "~*.log"));
                            if (fileList.Count >= _maxFiles - 1)
                            {
                                fileList.Sort();
                                for (int i = 0; i <= fileList.Count - _maxFiles + 1; i++)
                                    File.Delete((string)fileList[i]);
                            }

                            fi.MoveTo(Path.Combine(path, "~" + DateTime.Now.Ticks.ToString() + ".log"));
                            writer = File.CreateText(logFileSpec);
                        }
                        else
                        {
                            writer = File.AppendText(logFileSpec);
                        }
                    }

                    writer.WriteLine(log);
                    writer.Flush();

                    writer.Close();
                }
            }
            catch
            {
            }
        }

        /// <summary>
        /// Log application into file/eventviewer according to configuration of application file. 
        /// </summary>
        /// <param name="e">Valid instance of an exception object.</param>
        public static void Write(Exception e)
        {
            string log = new string('*', 80) + Environment.NewLine;
            log += string.Format("  TimeStamp: {0} {1}{2}", DateTime.Today.ToShortDateString(),
                DateTime.Now.ToLongTimeString(), Environment.NewLine);
            log += new string('*', 80) + Environment.NewLine;

            while (e != null)
            {
                log += Environment.NewLine;
                log += string.Format("Exception..: {0}{1}", e.GetType().Name, Environment.NewLine);
                log += string.Format("Source.....: {0}{1}", e.Source, Environment.NewLine);
                log += string.Format("Message....: {0}{1}", e.Message, Environment.NewLine);
                log += string.Format("Stack Trace: {0}", e.StackTrace.Trim());
                e = e.InnerException;
                log += Environment.NewLine + new string('-', 80) + Environment.NewLine;
            }

            if (_mode == "EventLog")
            {
                WriteToEventLog(log);
            }
            else if (_mode == "File")
            {
                WriteToFile(log);
            }
        }

        /// <summary>
        /// Log application into file/eventviewer according to configuration of application file. 
        /// </summary>
        /// <param name="e">Valid instance of an ServiceException object.</param>
        /// ####
        //public static void Write(ServiceException e)
        //{
        //    Write(e as Exception);
        //}
        private ExceptionLog()
        {
        }
    }

    internal sealed class AppConfigParser
    {
        private Dictionary<string, string> _attributes;

        public void Parse(string configValue)
        {
            _attributes = new Dictionary<string, string>();

            string[] segments = configValue.Trim().Split(';');
            foreach (string segment in segments)
            {
                string[] keyValue = segment.Trim().Split('=');
                if (keyValue.Length != 2)
                    continue;

                string key = keyValue[0].Trim();
                string value = keyValue[1].Trim();

                _attributes.Add(key, value);
            }
        }

        public bool Contains(string key)
        {
            return _attributes.ContainsKey(key);
        }

        public string this[string key]
        {
            get { return _attributes[key]; }
        }

        public AppConfigParser()
        {
        }
    }

    #endregion
}