using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FairyGUI;
using SGModule.Common.Base;
using SGModule.Common.Helper;
using UnityEngine;
using UnityEngine.Networking;

namespace SGModule.MarkdownKit {
    public class MarkdownKit : SingletonMonoBehaviour<MarkdownKit> {
        /// <summary>
        ///     加载文本，直接去网络下载
        /// </summary>
        /// <param name="key">自己为Md相关数据起的名字，后续都是通过这个来操作</param>
        /// <param name="textSize">文字默认大小</param>
        /// <param name="url">md下载地址</param>
        public void LoadText(string key, string url, int textSize = 40) {
            var data = new MarkdownData { Url = url, BaseSize = textSize };
            if (!MarkdownDataMgr.TryAdd(key, data)) {
                Log.MarkdownKit.Warning($"{key} 已加载，请勿重复加载！！！");
                return;
            }

            StartCoroutine(Download(data));
        }

        /// <summary>
        ///     获取指定的文本数据
        /// </summary>
        /// <param name="key">自定义键名</param>
        /// <param name="onComplete">获取回调</param>
        /// <param name="textSize">文本大小</param>
        public void GetText(string key, Action<bool, List<string>> onComplete, int textSize = 40) {
            if (!MarkdownDataMgr.TryGetValue(key, out var data)) {
                Log.MarkdownKit.Warning($"{key} 未初始化，请加载后重试");
                return;
            }

            SetMarkdownTextSize(data, textSize);

            switch (data.State) {
                case MarkdownTextState.Complete:
                    onComplete?.Invoke(true, data.RichTextList);
                    return;
                case MarkdownTextState.Downloading:
                    data.OnComplete += onComplete;
                    return;
                case MarkdownTextState.Exception:
                    data.OnComplete += onComplete;
                    StartCoroutine(Download(data));
                    break;
            }
        }

        /// <summary>
        ///     下载md
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private IEnumerator Download(MarkdownData data) {
            data.State = MarkdownTextState.Downloading;

            var unityWebRequest = new UnityWebRequest(data.Url) {
                downloadHandler = new DownloadHandlerBuffer()
            };

            unityWebRequest.SetRequestHeader("Content-Type", "application/json;charset=utf-8");

            yield return unityWebRequest.SendWebRequest(); //发送请求

            if (unityWebRequest.result is not UnityWebRequest.Result.Success) {
                data.State = MarkdownTextState.Exception;
                data.OnComplete?.Invoke(false, null);
                Log.MarkdownKit.Error($"失败 {unityWebRequest.result} {unityWebRequest.error}");
            }
            else {
                var receiveContent = unityWebRequest.downloadHandler.text;

                data.Text = receiveContent;
                data.MarkdownTextList = SplitMarkdownByHeaders(receiveContent);
                UpdateMarkdownTextList(data);
                data.State = MarkdownTextState.Complete;

                data.OnComplete?.Invoke(true, data.RichTextList);
            }

            data.OnComplete = null;
        }

        /// <summary>
        ///     根据md标题切割md文本
        /// </summary>
        /// <param name="markdownText"></param>
        /// <returns></returns>
        private List<string> SplitMarkdownByHeaders(string markdownText) {
            var sections = new List<string>();
            var currentSection = new StringBuilder();

            using (var reader = new StringReader(markdownText)) {
                string line;
                while ((line = reader.ReadLine()) != null) {
                    if (line.StartsWith("#")) // 如果是标题行
                    {
                        if (currentSection.Length > 0) {
                            sections.Add(currentSection.ToString());
                            currentSection.Clear();
                        }
                    }

                    currentSection.AppendLine(line);
                }

                if (currentSection.Length > 0) // 添加最后一段
                {
                    sections.Add(currentSection.ToString());
                }
            }

            return sections;
        }

        /// <summary>
        ///     设置富文本默认文字大小
        /// </summary>
        /// <param name="data"></param>
        /// <param name="textSize"></param>
        private void SetMarkdownTextSize(MarkdownData data, int textSize) {
            if (textSize > 0 && data.BaseSize != textSize) {
                data.BaseSize = textSize;

                UpdateMarkdownTextList(data);
            }
        }

        /// <summary>
        ///     更新富文本数据
        /// </summary>
        /// <param name="data"></param>
        private void UpdateMarkdownTextList(MarkdownData data) {
            if (data.MarkdownTextList == null) {
                return;
            }

            var richTextList = new List<string>();
            foreach (var section in data.MarkdownTextList) {
                var richText = MarkdownConvert.ToUBB(section, data.BaseSize);

                richTextList.Add(richText);
            }

            data.RichTextList = richTextList;
        }

        /// <summary>
        ///     添加富文本到指定节点下
        /// </summary>
        /// <param name="parent">指定节点</param>
        /// <param name="key">数据键名</param>
        /// <param name="color">颜色</param>
        /// <param name="callback">回调，参数分是代表了结果与当前状态</param>
        /// <param name="textSize">字体大小，如果与当前不一致将更新富文本数据</param>
        public void ShowAsRichText(GComponent parent, string key, Color color, Action<bool, MarkdownTextState> callback, int textSize = -1) {
            //处理对象为空或者相关对象已经被销毁的情况，如界面在等待过程中已经被关闭
            if (parent == null || parent.isDisposed) {
                Log.MarkdownKit.Warning("parent 是无效的");
                return;
            }

            if (!MarkdownDataMgr.TryGetValue(key, out var data)) {
                Log.MarkdownKit.Error($"未加载 {key}的数据");
                callback?.Invoke(false, MarkdownTextState.None);
                return;
            }

            Action<List<string>> show = list => {
                //处理对象为空或者相关对象已经被销毁的情况，如界面在等待过程中已经被关闭
                if (parent == null || parent.isDisposed) {
                    Log.MarkdownKit.Warning("parent 是无效的");
                    return;
                }

                SetMarkdownTextSize(data, textSize);
                foreach (var richText in list) {
                    // 创建 GRichTextField
                    var aRichTextField = new GRichTextField();

                    aRichTextField.UBBEnabled = true;
                    aRichTextField.SetSize(parent.size.x, 0);
                    aRichTextField.color = color;
                    aRichTextField.textFormat.size = data.BaseSize;
                    aRichTextField.autoSize = AutoSizeType.Height;
                    aRichTextField.AddRelation(GRoot.inst, RelationType.Width);
                    aRichTextField.text = richText;
                    parent.AddChild(aRichTextField);
                }
            };

            Action<bool, List<string>> downloadingCallback = (result, list) => {
                callback?.Invoke(result, data.State);
                if (result) {
                    show.Invoke(list);
                }
            };

            switch (data.State) {
                case MarkdownTextState.Downloading:
                    callback?.Invoke(true, data.State);
                    data.OnComplete += downloadingCallback;
                    break;
                case MarkdownTextState.Complete:
                    callback?.Invoke(true, data.State);
                    show.Invoke(data.RichTextList);
                    break;
                case MarkdownTextState.Exception:
                    callback?.Invoke(true, data.State);
                    data.OnComplete += downloadingCallback;
                    StartCoroutine(Download(data));
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}
