﻿using System.Collections;

namespace AsmodeeDigital.Common.Plugin.Utils
{
    /// <summary>
    /// This class helps to logs events of the Unity Plugin in a stantardized and
    /// easily parsable way.
    /// Debug and Info levels are not logged in release builds.
    /// </summary>
    public static class AsmoLogger
    {
        public enum Severity
        {
            Trace,
            Debug,
            Info,
            Notice,
            Warning,
            Error,
            Fatal
        }

        public static Severity LogLevel { get; set; }
        public static bool IsDebugBuild { get; private set; }

        static AsmoLogger()
        {
            IsDebugBuild = UnityEngine.Debug.isDebugBuild;
            LogLevel = IsDebugBuild ? Severity.Debug : Severity.Info;
            Debug("AsmoLogger", "AsmoLogger initialized", new Hashtable() { { "IsDebugBuild", IsDebugBuild } });
        }

        public static void Trace(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Trace, module, message, extraInfo);
        }

        public static void Debug(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Debug, module, message, extraInfo);
        }

        public static void Info(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Info, module, message, extraInfo);
        }

        public static void Notice(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Notice, module, message, extraInfo);
        }

        public static void Warning(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Warning, module, message, extraInfo);
        }

        public static void Error(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Error, module, message, extraInfo);
        }

        public static void Fatal(string module, string message, Hashtable extraInfo = null)
        {
            Log(Severity.Fatal, module, message, extraInfo);
        }

        public static void Log(Severity severity, string module, string message, Hashtable extraInfo = null)
        {
            if (severity < LogLevel)
            {
                return;
            }

            string fullMessage = string.Format(
                "[{0}][{1}][{2}] {3}",
                System.DateTime.UtcNow.ToString("o"),
                severity,
                module,
                message);

            if (extraInfo != null && extraInfo.Count > 0)
            {
                string json = MiniJSON.Json.Serialize(extraInfo);
                fullMessage += " " + json;
            }

            switch (severity)
            {
                case Severity.Error:
                case Severity.Fatal:
                    UnityEngine.Debug.LogError(fullMessage);
                    break;

                case Severity.Warning:
                case Severity.Notice:
                    UnityEngine.Debug.LogWarning(fullMessage);
                    break;

                default:
                    UnityEngine.Debug.Log(fullMessage);
                    break;
            }
        }

        public static void LogException(System.Exception ex, string moduleName, AsmoLogger.Severity severity = AsmoLogger.Severity.Error)
        {
            string innerType = (ex.InnerException != null) ? ex.InnerException.GetType().ToString() : null;
            string innerMessage = (ex.InnerException != null) ? ex.InnerException.Message : null;
            AsmoLogger.Log(severity, moduleName, "Inner Exception", new Hashtable() {
                {"type", ex.GetType().ToString()},
                {"message", ex.Message},
                {"inner_type", innerType},
                {"inner_message", innerMessage},
                {"stack", ex.StackTrace}
            });
        }
    }
}
