using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace Wayne.Lib
{
    /// <summary>
    /// General handling of the application level unhandled exceptions.
    /// </summary>
    public static class ExceptionHandling
    {
        static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("Application");

        /// <summary>
        /// Create and register eventhandlers.
        /// </summary>
        public static void CatchUnhandledException()
        {
            AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        /// <summary>
        /// The eventhandler for Exceptions in the current domain.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            UnhandledException(e.ExceptionObject);
        }


        /// <summary>
        /// Handling a unhandled exception by creating a log.
        /// </summary>
        /// <param name="oException"></param>
        public static void UnhandledException(object oException)
        {
            try
            {
                try
                {
                    LogCrashError(oException);
                }
                catch
                {
                }
            }
            finally
            {
                var thisProcess = Process.GetCurrentProcess();
                thisProcess.Kill();
            }
        }

        /// <summary>
        /// Writes the exception to the logfile.
        /// </summary>
        /// <param name="oException"></param>
        private static void LogCrashError(object oException)
        {
            logger.Error(GetExceptionInfo(oException as Exception, string.Empty));
            //FileSupport.EnsureDirectoryExists(@"\Flash\Logs\");
            //using (var sw = new StreamWriter(string.Format(@"\Flash\Logs\CrashLog_{0}.txt",
            //    DateTime.Today.ToString("yyyyMMdd")), true))
            //{
            //    sw.WriteLine("**********************************************************************");
            //    sw.WriteLine(string.Format("* {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now));
            //    sw.Write(GetExceptionInfo(oException as Exception, string.Empty));
            //}
        }

        /// <summary>
        /// Exctracts the information from the Exception object.
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="indent"></param>
        /// <returns></returns>
        private static string GetExceptionInfo(Exception exception, string indent)
        {
            var text = new StringBuilder();
            if (exception != null)
            {
                text.Append(string.Concat("Exception of type ", exception.GetType().FullName, "\r\n"));
                text.Append(string.Concat("Message: \"", exception.Message, "\"\r\n"));

                var se = exception as System.Net.Sockets.SocketException;
                if (se != null)
                {
                    text.Append(string.Concat("Socket ErrorCode: ", se.ErrorCode, "\r\n"));
                    text.Append(string.Concat("Socket NativeErrorCode: ", se.NativeErrorCode, "\r\n"));

                }

                text.Append(string.Concat("StackTrace:\r\n", exception.StackTrace, "\r\n"));
                if (exception.InnerException != null)
                {
                    text.Append("Inner Exception:\r\n");
                    text.Append(GetExceptionInfo(exception.InnerException, "   "));
                }
            }
            else
                text.Append("Exception object is null");

            var indentedText = new StringBuilder();
            foreach (var line in Regex.Split(text.ToString(), "\r\n"))
                indentedText.Append(string.Concat(indent, line, "\r\n"));
            return indentedText.ToString();
        }
    }
}