using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI;
using System;
using System.Threading.Tasks;
using System.Threading;
namespace GFGGame
{
    /// 
    /// 使用异步函数实现多个字同时渐变
    /// 
    public class TypingFadeEffectPro: TypingEffect
    {
        protected Color32[] _backupColor32s;
        protected Color32[] _color32s;
        public Action typeFinishedAction;
        // 出现下一个字符的间隔
        protected float showNextWordInternal = 0.06f;
        // 字符渐变时间
        protected float charFadeDuration = 0.15f;
        // 异步函数的取消控制
        private CancellationTokenSource _cancellationTokenSource;
        /// 
        /// 
        /// 
        /// 
        public TypingFadeEffectPro(TextField textField) : base(textField) { }
        /// 
        /// 
        /// 
        /// 
        public TypingFadeEffectPro(GTextField textField) : base(textField) { }
        /// 
        /// 开始打字效果。可以重复调用重复启动。
        /// 
        public new void Start()
        {
            _textField.graphics.meshModifier -= OnMeshModified;
            _textField.Redraw();
            _textField.graphics.meshModifier += OnMeshModified;
            _stroke = false;
            _shadow = false;
            _strokeDrawDirs = 4;
            _mainLayerStart = 0;
            _mainLayerVertCount = 0;
            _printIndex = 0;
            _vertIndex = 0;
            _started = true;
            _cancellationTokenSource = new CancellationTokenSource();
            int vertCount = _textField.graphics.mesh.vertexCount;
            UpdateBackUp();
            // Clear mesh info
            if (_vertices == null || _vertices.Length != vertCount)
                _vertices = new Vector3[vertCount];
            if (_color32s == null || _color32s.Length != vertCount)
            {
                _color32s = new Color32[vertCount];
            }
            Vector3 zero = Vector3.zero;
            for (int i = 0; i < vertCount; i++)
                _vertices[i] = zero;
            _textField.graphics.mesh.vertices = _vertices;
            //隐藏所有混排的对象
            if (_textField.richTextField != null)
            {
                int ec = _textField.richTextField.htmlElementCount;
                for (int i = 0; i < ec; i++)
                    _textField.richTextField.ShowHtmlObject(i, false);
            }
            int charCount = _textField.charPositions.Count;
            for (int i = 0; i < charCount; i++)
            {
                TextField.CharPosition cp = _textField.charPositions[i];
                _mainLayerVertCount += cp.vertCount;
            }
            if (_mainLayerVertCount < vertCount) //说明有描边或者阴影
            {
                int repeat = vertCount / _mainLayerVertCount;
                _stroke = repeat > 2;
                _shadow = repeat % 2 == 0;
                _mainLayerStart = vertCount - vertCount / repeat;
                _strokeLayerStart = _shadow ? (vertCount / repeat) : 0;
                _strokeDrawDirs = repeat > 8 ? 8 : 4;
            }
            Timers.inst.StartCoroutine(UpdateFadeProgress());
        }
        public void PrintFade(int printIndex, byte alpha, int vertIndex)
        {
            TextField.CharPosition cp;
            List charPositions = _textField.charPositions;
            int listCnt = charPositions.Count;
            cp = charPositions[printIndex];
            if (cp.vertCount > 0)
                output(cp.vertCount, alpha, vertIndex);
            if (cp.imgIndex > 0) //这是一个图片
            {
                _textField.richTextField.ShowHtmlObject(cp.imgIndex - 1, true);
                return;
            }
            else if (!char.IsWhiteSpace(_textField.parsedText[Mathf.Max(printIndex - 1, 0)]))
                return;
        }
        private void output(int vertCount, byte alpha, int vertIndex)
        {
            int start, end;
            start = _mainLayerStart + vertIndex;
            end = start + vertCount;
            //Vector3[] vertices = new Vector3[end - start];
            for (int i = start; i < end; i++)
            {
                _vertices[i] = _backupVerts[i];
                _color32s[i] = _backupColor32s[i];
                _color32s[i].a = alpha;
            }
                
            if (_stroke)
            {
                start = _strokeLayerStart + vertIndex;
                end = start + vertCount;
                for (int i = start; i < end; i++)
                {
                    for (int j = 0; j < _strokeDrawDirs; j++)
                    {
                        int k = i + _mainLayerVertCount * j;
                        _vertices[k] = _backupVerts[k];
                    }
                }
            }
            if (_shadow)
            {
                start = vertIndex;
                end = start + vertCount;
                for (int i = start; i < end; i++)
                {
                    _vertices[i] = _backupVerts[i];
                }
            }
            _textField.graphics.mesh.vertices = _vertices;
            _textField.graphics.mesh.colors32 = _color32s;
        }
        public new void Cancel()
        {
            if (!_started)
                return;
            StopMyAsyncFunction();
            _started = false;
            _textField.graphics.meshModifier -= OnMeshModified;
            _textField.graphics.SetMeshDirty();
        }
        /// 
        /// 当打字过程中,文本可能会由于字体纹理更改而发生字体重建,要处理这种情况。
        /// 图片对象不需要处理,因为HtmlElement.status里设定的隐藏标志不会因为Mesh更新而被冲掉。
        /// 
        void OnMeshModified()
        {
            if (_textField.graphics.mesh.vertexCount != _backupVerts.Length) //可能文字都改了
            {
                Cancel();
                return;
            }
            UpdateBackUp();
            int vertCount = _vertices.Length;
            Vector3 zero = Vector3.zero;
            for (int i = 0; i < vertCount; i++)
            {
                if (_vertices[i] != zero)
                    _vertices[i] = _backupVerts[i];
            }
            _textField.graphics.mesh.vertices = _vertices;
        }
        IEnumerator UpdateFadeProgress()
        {
            List charPositions = _textField.charPositions;
            int listCnt = charPositions.Count;
            float timer = 0;
            //for(int i=0;i<= listCnt - 1; i++)
            //{
            //    PrintFade(i, 0, _vertIndex);
            //    _vertIndex += charPositions[_printIndex].vertCount;
            //}
            //_vertIndex = 0;
            while (true)
            {
                if (!_started)
                    break;
                if(timer>= showNextWordInternal)
                {
                    timer = 0;
                    if (_printIndex >= listCnt - 1)
                    {
                        Cancel();
                        typeFinishedAction.Invoke();
                        break;
                    }
                    else
                    {
                        UpdateFadeProgressSingle(_printIndex, _vertIndex, _cancellationTokenSource.Token);
                        ++_printIndex;
                        if(_printIndex < listCnt - 1 && _printIndex < charPositions.Count)
                        {
                            _vertIndex += charPositions[_printIndex].vertCount;
                        }
                    }
                }
                timer += Time.deltaTime;
                yield return new WaitForEndOfFrame();
            }
        }
        async Task UpdateFadeProgressSingle(int printIndex, int vertIndex, CancellationToken cancellationToken)
        {
            float _currentCharFadeTime = 0;
            while (true)
            {
                if (!_started)
                    break;
                _currentCharFadeTime += 0.016f;
                float progress = _currentCharFadeTime / charFadeDuration;
                if (progress >= 1)
                {
                    PrintFade(printIndex, 255, vertIndex);
                    break;
                }
                else
                {
                    byte alpha = (byte)(progress * 255);
                    PrintFade(printIndex, alpha, vertIndex);
                }
                await Task.Delay(16, cancellationToken);
            }
        }
        // Back up origin text info
        protected void UpdateBackUp()
        {
            _backupVerts = _textField.graphics.mesh.vertices;
            _backupColor32s = _textField.graphics.mesh.colors32;
        }
        public void SetSpeed(float speed)
        {
            //charFadeDuration /= speed;
            showNextWordInternal /= speed;
            charFadeDuration = showNextWordInternal + 0.05f;
        }
        // 取消异步函数
        public void StopMyAsyncFunction()
        {
            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Cancel();
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;
            }
        }
    }
}