using System;
using System.Collections;
using System.Diagnostics;
using System.Text;

namespace EonaCat.Logger.Extensions
{
    public static class ExceptionExtensions
    {
        public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
        {
            if (exception == null)
                return string.Empty;

            var st = new StackTrace(exception, true);
            var frame = st.GetFrame(0);
            int fileLine = frame.GetFileLineNumber();
            string filename = frame.GetFileName();

            StringBuilder sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine("--- Exception details provided by EonaCatLogger ---");
            if (!string.IsNullOrEmpty(module))
                sb.AppendLine("  Module     : " + module);
            if (!string.IsNullOrEmpty(method))
                sb.AppendLine("  Method     : " + method);
            sb.Append("  Type       : ").AppendLine(exception.GetType().ToString());
            sb.Append("  Data       : ").AppendLine(exception.Data != null && exception.Data.Count > 0 ? FormatExceptionData(exception.Data) : "(none)");
            sb.Append("  Inner      : ").AppendLine(exception.InnerException != null ? FormatInnerException(exception.InnerException) : "(null)");
            sb.Append("  Message    : ").AppendLine(exception.Message);
            sb.Append("  Source     : ").AppendLine(exception.Source);
            sb.Append("  StackTrace : ").AppendLine(exception.StackTrace);
            sb.Append("  Line       : ").AppendLine(fileLine.ToString());
            sb.Append("  File       : ").AppendLine(filename);
            sb.Append("  ToString   : ").AppendLine(exception.ToString());
            sb.AppendLine("---");

            return sb.ToString();
        }

        private static string FormatExceptionData(IDictionary data)
        {
            StringBuilder sb = new StringBuilder();

            foreach (DictionaryEntry entry in data)
            {
                sb.Append("  | ")
                    .Append(entry.Key)
                    .Append(": ")
                    .AppendLine(entry.Value.ToString());
            }

            return sb.ToString();
        }

        private static string FormatInnerException(Exception innerException)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(innerException.GetType().ToString())
                .AppendLine("    Message    : " + innerException.Message)
                .AppendLine("    Source     : " + innerException.Source)
                .AppendLine("    StackTrace : " + innerException.StackTrace)
                .AppendLine("    ToString   : " + innerException.ToString())
                .Append("    Data       : ")
                .AppendLine(innerException.Data != null && innerException.Data.Count > 0 ? FormatExceptionData(innerException.Data) : "(none)");

            return sb.ToString();
        }
    }
}
