
using XGame.Framework.Logger;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using XGame.Framework;

namespace XGame
{
    public static class Log
    {
        private static ILogger _log;
        private static ILogger log => _log ?? (_log = LogCreator.Create());

        #region utility

        private static string ParseException(System.Exception exception)
        {
            string result = string.Format("{0}: {1}\nStackTrace: {2}", exception.GetType().FullName, exception.Message, exception.StackTrace);

            if (exception.InnerException != null)
            {
                var innerResult = ParseException(exception.InnerException);
                result = string.Format("{0}\n[InnerException]\n{1}", result, innerResult);
            }
            return result;
        }

        #endregion

        #region Debug

        /// <summary>
        /// 细粒度级别，用于开发过程中的调试使用，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR)]
#if !PROFILER
        [Conditional(MacroDefine.DEBUG)]
#endif
        public static void Debug(string format, params object[] args)
        {
            var result = log.Log(LogLevel.Debug, format, args);

            UnityEngine.Debug.Log(result);
        }

        /// <summary>
        /// 细粒度级别，用于开发过程中的调试使用，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR)]
#if !PROFILER
        [Conditional(MacroDefine.DEBUG)]
#endif
        public static void Debug(object obj)
        {
            var result = log.Log(LogLevel.Debug, obj.ToString());

            UnityEngine.Debug.Log(result);
        }

        #endregion

        #region Info
        /// <summary>
        /// 粗粒度级别，用于运行过程中突出强调应用程序的运行过程(eg:LogSystem init success/fail)，所有版本可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Info(string format, params object[] args)
        {
            var result = log.Log(LogLevel.Info, format, args);

            UnityEngine.Debug.Log(result);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中突出强调应用程序的运行过程(eg:LogSystem init success/fail)，所有版本可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Info(object obj)
        {
            var result = log.Log(LogLevel.Info, obj.ToString());

            UnityEngine.Debug.Log(result);
        }
        #endregion

        #region Warn
        /// <summary>
        /// 粗粒度级别，用于运行过程中表明会出现潜在错误的情形，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER)]
        public static void Warn(string format, params object[] args)
        {
            var result = log.Log(LogLevel.Warn, format, args);

            UnityEngine.Debug.LogWarning(result);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中表明会出现潜在错误的情形，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER)]
        public static void Warn(object obj)
        {
            var result = log.Log(LogLevel.Warn, obj.ToString());

            UnityEngine.Debug.LogWarning(result);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中表明会出现潜在错误的情形，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER)]
        public static void WarnException(System.Exception exception)
        {
            WarnException(null, exception);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中表明会出现潜在错误的情形，开发中与发布Debug版可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER)]
        public static void WarnException(string prefix, System.Exception exception)
        {
            if (null == exception)
            {
                Warn("{0} Exception is null.", prefix);
                return;
            }
            string exceptionStr = ParseException(exception);
            Warn("{0} {1}", prefix, exceptionStr);
        }

        #endregion

        #region Error
        /// <summary>
        /// 粗粒度级别，用于运行过程中虽然发生错误事件,但仍然不影响系统的继续运行，所有版本可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Error(string format, params object[] args)
        {
            var result = log.Log(LogLevel.Error, format, args);

            UnityEngine.Debug.LogError(result);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中虽然发生错误事件,但仍然不影响系统的继续运行，所有版本可见
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Error(object obj)
        {
            var result = log.Log(LogLevel.Error, obj.ToString());

            UnityEngine.Debug.LogError(result);
        }

        #endregion

        #region Exception

        /// <summary>
        /// 粗粒度级别，用于运行过程中指出每个严重的错误事件将会导致应用程序的退出，将上报后端保存，所有版本可见
        /// 级别与Error相当
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Exception(System.Exception exception)
        {
            Exception(null, exception);
        }

        /// <summary>
        /// 粗粒度级别，用于运行过程中指出每个严重的错误事件将会导致应用程序的退出，将上报后端保存，所有版本可见
        /// 级别与Error相当
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.PROFILER), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Exception(string prefix, System.Exception exception)
        {
            if (null == exception)
            {
                Log.Error("{0} Exception is null.", prefix);
                return;
            }

            string exceptionStr = ParseException(exception);
            var result = log.Log(LogLevel.Exception, $"{prefix} {exceptionStr}");
            UnityEngine.Debug.LogError(result);
        }

        #endregion

        #region 埋点接口

        /// <summary>
        /// 埋点接口 缓存至本地-实时上传至后端-多用于数据分析统计
        /// </summary>
        /// <param name="format">格式化字符串</param>
        /// <param name="args">不定长格式化参数</param>
        [Conditional(MacroDefine.UNITY_EDITOR), Conditional(MacroDefine.DEBUG), Conditional(MacroDefine.FINAL_RELEASE)]
        public static void Event(string type, string id, Dictionary<string, string> infos)
        {
            var result = log.Event(type, id, infos);
            UnityEngine.Debug.Log(result);
        }

        #endregion

        #region 其他

        /// <summary>
        /// 日志是否将会保存至本地缓存
        /// 用于日志上传模块判断是否需要开启上传
        /// </summary>
        public static bool IsSaveLocalCache()
        {
            return _log is ILogFlushable;
        }



        public static void Initialize()
        {
            log.Initialize();
        }

        public static void Dispose()
        {
            (_log as IDisposable)?.Dispose();
            _log = null;
        }

        /// <summary>
        /// 强制写入日志
        /// </summary>
        internal static void Flush(int type)
        {
            (_log as ILogFlushable)?.Flush((LogType)type);
        }

        #endregion
    }
}
