using TFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;

namespace TFramework
{
    public class Console : BaseComponent
    {
        public Toggle m_infoTog;
        public Text m_infoCountText;
        public Toggle m_warningTog;
        public Text m_warningCountText;
        public Toggle m_errorTog;
        public Text m_errorCountText;
        public Button m_clearBtn;

        public Toggle m_logItem;
        private List<Toggle> m_logItems = new List<Toggle>();

        public InputField m_logInfoText;
        public Text m_logInfoContent;

        private List<ConsoleLog> _infoLogs = new List<ConsoleLog>();
        private List<ConsoleLog> _errorLogs = new List<ConsoleLog>();
        private List<ConsoleLog> _warningLogs = new List<ConsoleLog>();

        private List<ConsoleLog> _logBuffers = new List<ConsoleLog>();

        string msg;
        bool _isDestroy = false;
        // Start is called before the first frame update
        void Start()
        {
            //m_logInfoText.onValueChanged.AddListener(st =>
            //{
            //    if (st != msg)
            //        m_logInfoText.text = msg;
            //});
        }

        public override void Init()
        {
            base.Init();
            Clear();
            Application.logMessageReceived += OnLogMessageReceived;
            m_clearBtn.onClick.AddListener(Clear);

            m_infoTog.onValueChanged.AddListener(isOn => Refresh());
            m_warningTog.onValueChanged.AddListener(isOn => Refresh());
            m_errorTog.onValueChanged.AddListener(isOn => Refresh());

            Main.Instance.Delay(0.2f, () =>
            {
                m_infoTog.isOn = true;
                m_warningTog.isOn = true;
                m_errorTog.isOn = true;
            });
        }

        private void Refresh()
        {
            m_logItems.ForEach(i => i.SetActive(false));
            msg = string.Empty;
            m_logInfoText.text = string.Empty;
            _logBuffers.Clear();
            if(m_infoTog.isOn)
                _logBuffers.AddRange(_infoLogs);
            if(m_warningTog.isOn)
                _logBuffers.AddRange(_warningLogs);
            if( m_errorTog.isOn)
                _logBuffers.AddRange(_errorLogs);

            _logBuffers.Sort((a,b)=>a.Time.CompareTo(b.Time));

            for (int i = 0; i < _logBuffers.Count; i++)
            {
                if (m_logItems.Count <= i)
                {
                    m_logItems.Add(m_logItem.Clone(m_logItem.transform.parent));
                }
                int index = i;
                m_logItems[i].gameObject.SetActive(true);
                m_logItems[i].GetChildComponent<Text>("Label").text = $"<color={(_logBuffers[i].Type == LogType.Log ? "white" : (_logBuffers[i].Type==LogType.Warning?"yellow":"red"))}>{_logBuffers[i].Name}</color>";
                m_logItems[i].onValueChanged.RemoveAllListeners();
                m_logItems[i].onValueChanged.AddListener (isOn =>
                {
                    if (isOn)
                    {
                        msg = $"<color={(_logBuffers[index].Type == LogType.Log ? "white" : (_logBuffers[index].Type == LogType.Warning ? "yellow" : "red"))}>{_logBuffers[index].Message}</color>\n{_logBuffers[index].StackTrace}";
                        m_logInfoContent.text = $"{_logBuffers[index].Message}\n{_logBuffers[index].StackTrace}";
                        m_logInfoText.text = msg;
                    }
                });
            }
        }

        private void OnLogMessageReceived(string condition, string stackTrace, LogType type)
        {
            ConsoleLog log = new ConsoleLog();
            log.Time = DateTime.Now;
            log.Message = condition;
            log.StackTrace = stackTrace;
            if (type == LogType.Assert)
            {
                log.Type = LogType.Error;
                _errorLogs.Add(log);
            }
            else if (type == LogType.Exception || type == LogType.Error)
            {
                log.Type = LogType.Error;
                _errorLogs.Add(log);
            }
            else if (type == LogType.Warning)
            {
                log.Type = LogType.Warning;
               _warningLogs.Add(log);
            }
            else if (type == LogType.Log)
            {
                log.Type = LogType.Log;
                _infoLogs.Add(log);
            }
            log.Name = string.Format("[{0}] [{1}] {2}", log.Type, log.Time.ToString("HH:mm:ss"), log.Message);
            if (_isDestroy||m_errorCountText==null||m_infoCountText==null|m_warningCountText==null) return;
            m_errorCountText.text = _errorLogs.Count < 99 ? _errorLogs.Count.ToString() : "99+";
            m_infoCountText.text = _infoLogs.Count < 99 ? _infoLogs.Count.ToString() : "99+";
            m_warningCountText.text = _warningLogs.Count < 99 ? _warningLogs.Count.ToString() : "99+";
            Refresh();
        }

        private void Clear()
        {
            _infoLogs.Clear();
            _warningLogs.Clear();
            _errorLogs.Clear();
            m_errorCountText.text = string.Empty;
            m_infoCountText.text = string.Empty;
            m_warningCountText.text = string.Empty;
            m_logItems.ForEach(i=>i.SetActive(false));
            m_logInfoText.text = string.Empty;
            m_infoCountText.text = string.Empty;
        }


        private void OnDestroy()
        {
            _isDestroy = true;
            Application.logMessageReceived -= OnLogMessageReceived;
        }
    }

}
