// using UnityEngine;
//
// using System;
// using System.Collections.Generic;
// using Cysharp.Threading.Tasks;
// using Cysharp.Threading.Tasks.Triggers;
// using TMPro;
// using UnityEngine;
// using UnityEngine.Pool;
// using System.Threading;
// using System.Runtime.CompilerServices;
// using Cysharp.Text;
//
// namespace  text
// {
//     public static class ZeroGCTypewriterPro
//     {
//         #region 核心结构体
//
//         private struct TypewriterHandle : IEquatable<TypewriterHandle>
//         {
//             public int InstanceID;
//             public int Version;
//
//             public bool Equals(TypewriterHandle other) =>
//                 InstanceID == other.InstanceID && Version == other.Version;
//         }
//
//         private struct TypewriterJob
//         {
//             public TypewriterHandle Handle;
//             public TMP_Text Target;
//             public string Content;
//             public float Speed;
//             public int LoopCount;
//             public Action<int> OnUpdate;
//             public Action OnComplete;
//             public CancellationToken ExternalToken;
//         }
//
//         #endregion
//
//         #region 状态管理
//
//         private static readonly Dictionary<int, ActiveJob> activeJobs =
//             new Dictionary<int, ActiveJob>(32);
//
//         private struct ActiveJob
//         {
//             public int Version;
//             public CancellationTokenSource Cts;
//         }
//
//         private static readonly ObjectPool<CancellationTokenSource> ctsPool =
//             ObjectPool<CancellationTokenSource>(
//                 createFunc: () => new CancellationTokenSource(),
//                 actionOnRelease: cts => cts.Cancel(),
//                 collectionCheck: false
//             );
//
//         #endregion
//
//         #region 公开接口
//
//         [MethodImpl(MethodImplOptions.AggressiveInlining)]
//         public static void Play(
//             this TMP_Text text,
//             string content,
//             float charsPerSecond = 30,
//             int loopCount = 0,
//             Action<int> onUpdate = null,
//             Action onComplete = null,
//             CancellationToken externalToken = default)
//         {
//             var instanceID = text.GetInstanceID();
//
//             // 停止当前任务（如果有）
//             if (activeJobs.TryGetValue(instanceID, out var existingJob))
//             {
//                 ctsPool.Release(existingJob.Cts);
//                 activeJobs.Remove(instanceID);
//             }
//
//             // 从对象池获取CTS
//             var cts = ctsPool.Get();
//             var linkedToken = CombineTokens(
//                 text.GetCancellationTokenOnDestroy(),
//                 externalToken,
//                 cts.Token
//             );
//
//             // 创建新任务
//             var newVersion = activeJobs.TryGetValue(instanceID, out var job) ? job.Version + 1 : 1;
//
//             activeJobs[instanceID] = new ActiveJob
//             {
//                 Version = newVersion,
//                 Cts = cts
//             };
//
//             RunJob(new TypewriterJob
//             {
//                 Handle = new TypewriterHandle
//                 {
//                     InstanceID = instanceID,
//                     Version = newVersion
//                 },
//                 Target = text,
//                 Content = content,
//                 Speed = Mathf.Max(0.01f, charsPerSecond),
//                 LoopCount = loopCount,
//                 OnUpdate = onUpdate,
//                 OnComplete = onComplete,
//                 ExternalToken = linkedToken
//             }).Forget();
//         }
//
//         [MethodImpl(MethodImplOptions.AggressiveInlining)]
//         public static void Stop(this TMP_Text text)
//         {
//             var instanceID = text.GetInstanceID();
//             if (activeJobs.TryGetValue(instanceID, out var job))
//             {
//                 ctsPool.Release(job.Cts);
//                 activeJobs.Remove(instanceID);
//                 ResetTextState(text);
//             }
//         }
//
//         #endregion
//
//         #region 核心逻辑
//
//         private static async UniTaskVoid RunJob(TypewriterJob job)
//         {
//             try
//             {
//                 var target = job.Target;
//                 using (var sb = ZString.CreateStringBuilder())
//                 {
//                     sb.Append(job.Content);
//                     target.text = sb.ToString();
//                     target.ForceMeshUpdate();
//
//                     int currentLoop = 0;
//                     var chars = sb.AsSpan();
//                     var interval = 1f / job.Speed;
//                     var timer = 0f;
//
//                     while (IsLoopValid(currentLoop, job.LoopCount))
//                     {
//                         target.maxVisibleCharacters = 0;
//
//                         for (int i = 0; i < chars.Length; i++)
//                         {
//                             // 版本校验
//                             if (!IsHandleValid(job.Handle)) return;
//
//                             // 基于时间的更新
//                             timer += Time.deltaTime;
//                             var required = (int)(timer * job.Speed);
//
//                             if (required > i)
//                             {
//                                 target.maxVisibleCharacters = required;
//                                 job.OnUpdate?.Invoke(required);
//                             }
//
//                             await UniTask.Yield(PlayerLoopTiming.Update, job.ExternalToken);
//                         }
//
//                         currentLoop++;
//                         timer = 0f;
//                         job.OnComplete?.Invoke();
//                     }
//                 }
//             }
//             finally
//             {
//                 if (IsHandleValid(job.Handle))
//                 {
//                     activeJobs.Remove(job.Handle.InstanceID);
//                     ResetTextState(job.Target);
//                 }
//             }
//         }
//
//         #endregion
//
//         #region 工具方法
//
//         [MethodImpl(MethodImplOptions.AggressiveInlining)]
//         private static bool IsHandleValid(TypewriterHandle handle)
//         {
//             return activeJobs.TryGetValue(handle.InstanceID, out var job) &&
//                    job.Version == handle.Version;
//         }
//
//         [MethodImpl(MethodImplOptions.AggressiveInlining)]
//         private static bool IsLoopValid(int current, int max) =>
//             max < 0 || current <= max;
//
//         private static CancellationToken CombineTokens(
//             CancellationToken token1,
//             CancellationToken token2,
//             CancellationToken token3)
//         {
//             if (token1.CanBeCanceled && token2.CanBeCanceled && token3.CanBeCanceled)
//                 return CancellationTokenSource.CreateLinkedTokenSource(
//                     token1, token2, token3).Token;
//
//             if (token1.CanBeCanceled && token2.CanBeCanceled)
//                 return CancellationTokenSource.CreateLinkedTokenSource(
//                     token1, token2).Token;
//
//             return token1.CanBeCanceled ? token1 : token2;
//         }
//
//         private static void ResetTextState(TMP_Text text)
//         {
//             if (text != null)
//             {
//                 text.maxVisibleCharacters = int.MaxValue;
//                 text.SetVerticesDirty();
//             }
//         }
//
//         private static CancellationToken GetCancellationTokenOnDestroy(this TMP_Text text)
//         {
//             return text.gameObject.GetCancellationTokenOnDestroy();
//         }
//
//         #endregion
//     }
//
// }
