using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace FantasyNetTest
{
    enum LogType
    {
        Info = 0,
        Warn = 1,
        Error = 2,
        Success = 3,
    }

    struct LogData
    {
        public LogType type;
        public string Content;

        public LogData(LogType type, string content)
        {
            this.type = type;
            this.Content = content;
        }
    }

    internal static class Log
    {
        private static readonly Queue<LogData> _logDatas = new Queue<LogData>();

        private static RichTextBox? _logTextBox;
        private static bool _init;

        public static void Init(RichTextBox? logTextBox)
        {
            _logTextBox = logTextBox;
            _init = true;
        }

        #region Input

        public static void Info(object obj, params object?[] args)
        {
            AddLog(LogType.Info, obj, args);
        }

        public static void Warn(object obj, params object?[] args)
        {
            AddLog(LogType.Warn, obj, args);
        }

        public static void Error(object obj, params object?[] args)
        {
            AddLog(LogType.Error, obj, args);
        }

        public static void Succeed(object obj, params object?[] args)
        {
            AddLog(LogType.Success, obj, args);
        }

        public static void AddLog(LogType type, object obj, params object?[] args)
        {
            if (!_init) return;
            string content;
            if (obj is string str)
            {
                content = str;
            }
            else
            {
                content = JsonSerializer.Serialize(obj);
            }

            if (!string.IsNullOrEmpty(content))
            {
                try
                {
                    content = string.Format(content, args);
                }
                catch
                {
                    // ignored
                }
            }

            _logDatas.Enqueue(new LogData { type = type, Content = content });
        }

        #endregion

        #region 显示相关

        public static void Tick()
        {
            if (_logDatas.Count < 1) return;

            var count = _logDatas.Count;

            for (int i = 0; i < count; i++)
            {
                AppendLog(_logDatas.Dequeue());
            }
        }

        private static void AppendLog(LogData logData)
        {
            if (logData.type == LogType.Error)
            {
                _logTextBox.AppendTextWithColor(logData.Content, Color.Crimson);
            }
            else if (logData.type == LogType.Warn)
            {
                _logTextBox.AppendTextWithColor(logData.Content, Color.Coral);
            }
            else if (logData.type == LogType.Success)
            {
                _logTextBox.AppendTextWithColor(logData.Content, Color.ForestGreen);
            }
            else
            {
                _logTextBox.AppendTextWithColor(logData.Content, Color.Black);
            }
        }


        public static void Clear()
        {
            if (!_init || _logTextBox == null) return;
            _logTextBox.Clear();
            _logTextBox.ScrollToCaret();
            _logTextBox.ResumeLayout();
        }

        private static void AppendTextWithColor(this RichTextBox? rtb, string text, Color color, bool addNewLine = true)
        {
            if (rtb == null) return;

            rtb.SuspendLayout();
            rtb.SelectionStart = rtb.TextLength;
            rtb.SelectionLength = 0;
            rtb.SelectionColor = color;
            rtb.AppendText(addNewLine ? $"{text}{Environment.NewLine}" : text);
            rtb.SelectionColor = rtb.ForeColor;

            rtb.ScrollToCaret();
            
            rtb.ResumeLayout();
        }
        

        #endregion
    }
}