﻿using System.Collections.Generic;
using UnityEngine;

namespace Utage
{
	//宴のTextMeshPro対応のタグ解析をさらにカスタムしてTextAnimatorに適用するクラス
	//下記のビルトインのタグに対応
	//https://www.febucci.com/text-animator-unity/docs/built-in-effects-list/
	public class TextParserForTextAnimator : TextMeshProTextParser
	{
		public TextParserForTextAnimator(string text, bool isParseParamOnly = false)
			:base(text, isParseParamOnly)
		{
		}
		
		
		//タグの解析。解析方法によってここをoverrideして処理
		protected override bool TryParseTag(int index, out int endIndex, out string tagName, out string tagArg)
		{
			bool result = base.TryParseTag(index, out endIndex, out tagName, out tagArg);
			if (result) return true;


			string name0 ="";
			string arg0 = "";
			// Here is TextAnimatorEvent Parsing Part.
			endIndex = ParserUtil.ParseTag(
				'<', '>',ParserUtil.DefaultTagSeparator,
				OriginalText, index, 
				(name,arg)=>
				{
					bool ret = ParseTagTextAnimatorEvents(name, arg);
					if (ret)
					{
						name0 = name;
						arg0 = arg;
					}
					return ret;
				});
			if (endIndex != index) return true;
			
			
			//Behaviors系のタグを解析する処理
			endIndex = ParserUtil.ParseTag(
				OriginalText, index, 
				(name,arg)=>
				{
					bool ret = ParseTagTextAnimatorBehaviors(name, arg);
					if (ret)
					{
						name0 = name;
						arg0 = arg;
					}
					return ret;
				});
			if(endIndex != index ) return true;
			
			//タグの区切り記号として { と } を使って、Appearances用のタグを解析する処理
			endIndex = ParserUtil.ParseTag(
				'{', '}',ParserUtil.DefaultTagSeparator,
				OriginalText, index, 
				(name,arg)=>
				{
					bool ret = ParseTagTextAnimatorAppearances(name, arg);
					if (ret)
					{
						name0 = name;
						arg0 = arg;
					}
					return ret;
				});
			tagName =name0;
			tagArg = arg0;
			return endIndex != index;
		}

		//独自定義イベントタグ用
		public static List<string> NewEventsTags { get; } = new(); 

		//テキストアニメーターのEvents用のタグか
		protected bool ParseTagTextAnimatorEvents(string name,string arg)
		{
			// Text Animator Must Start "<?" So Check ?
			if (!name.StartsWith("?"))
			{
				return false;
			}
			
			name = name.Substring(1);
			if (NewEventsTags.Contains(name))
			{
				return true;
			}
			return false;
		}
		
		//テキストアニメーター用のBehaviors用のタグ
		static readonly List<string> TextAnimatorBehaviorsTagTbl = new List<string>()
		{
			"pend","/pend",
			"dangle","/dangle",
			"fade","/fade",
			"rainb","/rainb",
			"rot","/rot",
			"bounce","/bounce",
			"slideh","/slideh",
			"slidev","/slidev",
			"swing","/swing",
			"wave","/wave",
			"incr","/incr",
			"shake","/shake",
			"wiggle","/wiggle",
		};
		
		//独自定義タグ用
		public static List<string> NewBehaviorTags { get; } = new(); 

		//テキストアニメーターのBehaviors用のタグか
		protected bool ParseTagTextAnimatorBehaviors(string name,string arg)
		{
			if (TextAnimatorBehaviorsTagTbl.Contains(name))
			{
				return true;
			}
			
			//nameの先頭が/の場合、削除する
			if (name.StartsWith("/"))
			{
				name = name.Substring(1);
			}
			if (NewBehaviorTags.Contains(name))
			{
				return true;
			}

			return false;
		}

		//テキストアニメーターのAppearances用のタグ
		static readonly List<string> TextAnimatorAppearancesTagTbl = new List<string>()
		{
			"pend","/pend",
			"dangle","/dangle",
			"fade","/fade",
			"rainb","/rainb",
			"rot","/rot",
			"bounce","/bounce",
			"slideh","/slideh",
			"slidev","/slidev",
			"swing","/swing",
			"wave","/wave",
			"incr","/incr",
			"shake","/shake",
			"wiggle","/wiggle",
		};

		//独自定義タグ用
		public static List<string> NewAppearancesTags { get; } = new(); 

		//テキストアニメーターのAppearances用のタグか
		protected bool ParseTagTextAnimatorAppearances(string name,string arg)
		{
			if (TextAnimatorAppearancesTagTbl.Contains(name))
			{
				return true;
			}

			//nameの先頭が/の場合、削除する
			if (name.StartsWith("/"))
			{
				name = name.Substring(1);
			}
			if (NewAppearancesTags.Contains(name))
			{
				return true;
			}
			return false;
		}
	}
}
