namespace Guru
{
    using System.Collections.Generic;
    using UnityEngine;
    using Firebase.Crashlytics;
    using System;
    using System.Linq;
    
    public static class CrashlyticsAgent
    {
        private static bool _initOnce;
        private static bool _isReady;

        private static Queue<Exception> _expCache;
        private static bool _hasSetUser = false;
        
        /// <summary>
        /// 捕获列表
        /// </summary>
        private static List<LogType> _catchFilter = new List<LogType>()
        {
            LogType.Exception,
        };
        
        /// <summary>
        /// 上报列表
        /// </summary>
        private static List<LogType> _logFilter = new List<LogType>()
        {
            LogType.Exception,
            LogType.Error,
            LogType.Assert,
        };

        public static void Install()
        {
            if (_initOnce) return;
            _initOnce = true;
            _expCache = new Queue<Exception>(20);
            
            Application.logMessageReceived -= OnReceivedMessage;
            Application.logMessageReceived += OnReceivedMessage;
            
            // Application.logMessageReceivedThreaded -= OnReceivedMessage;
            // Application.logMessageReceivedThreaded += OnReceivedMessage;

            if (FirebaseUtil.IsReady)
            {
                OnFirebaseComplete(true);
                return;
            }

            FirebaseUtil.onInitComplete -= OnFirebaseComplete;
            FirebaseUtil.onInitComplete += OnFirebaseComplete;
        }

        private static void OnFirebaseComplete(bool success)
        {
            FirebaseUtil.onInitComplete -= OnFirebaseComplete;
            if (success)
            {
                _isReady = true;
                Crashlytics.IsCrashlyticsCollectionEnabled = true;
                if (_expCache != null && _expCache.Count > 0)
                {
                    while (_expCache.Count > 0)
                    {
                        LogException(_expCache.Dequeue());
                    }
                    _expCache.Clear();
                }
            }
        }

        private static string ToLogTypeString(LogType type)
        {
            switch (type)
            {
                case LogType.Exception: return "ex";
                case LogType.Error: return "e";
                case LogType.Warning: return "w";
            }
            return "i";
        }


        private static void OnReceivedMessage(string condition, string stackTrace, LogType type)
        {
            
            string msg = $"{DateTime.Now:yy-MM-dd HH:mm:ss} [{ToLogTypeString(type)}] {condition}\n{stackTrace}";
            
            if (_catchFilter.Contains(type))
            {
                LogException(msg);
            }
            else if(_logFilter.Contains(type))
            {
                Log(msg);
            }
        }

        public static void LogException(Exception ex)
        {
            if (!_isReady)
            {
                Install();
                _expCache.Enqueue(ex);
                return;
            }
            Crashlytics.LogException(ex);
            // CheckSetUser();
        }

        public static void LogException(string msg)
        {
            LogException(new Exception(msg));
        }

        public static void Log(string msg)
        {
            if (!_isReady) return;
            Crashlytics.Log(msg);
            // CheckSetUser();
        }
        
        
        public static void SetCustomKey(string key, string value)
        {
            if (!_isReady) return;
            Crashlytics.SetCustomKey(key, value);
        }
        

    }
}