using System;
using System.Collections;
using System.Collections.Generic;
using HyperlinkText;
using UnityEngine.EventSystems;

namespace UnityEngine.UI
{
	[ExecuteInEditMode]
	public abstract class HyperTextBase : BaseMeshEffect, ICanvasRaycastFilter
	{
		private Canvas RootCanvas
		{
			get
			{
				Canvas result;
				if ((result = this._rootCanvas) == null)
				{
					result = (this._rootCanvas = base.GetComponentInParent<Canvas>());
				}
				return result;
			}
		}

		protected Text text
		{
			get
			{
				Text result;
				if ((result = this.m_TextComp) == null)
				{
					result = (this.m_TextComp = base.GetComponent<Text>());
				}
				return result;
			}
		}

		protected void RegisterClickable(int startIndex, int wordLength, string returnString, Color color, Action<string> onClick, Action<HyperTextBase.ClickableEntry> onEnter = null, Action<HyperTextBase.ClickableEntry> onExit = null)
		{
			if (onClick == null)
			{
				Debug.LogWarning("クリック時のイベントにnullが指定されました");
				return;
			}
			if (startIndex < 0 || wordLength < 0 || startIndex + wordLength > this.text.text.Length)
			{
				Debug.LogWarning("テキストの文字数範囲外です");
				return;
			}
			this._entries.Add(new HyperTextBase.ClickableEntry(this.text.text.Substring(startIndex, wordLength), startIndex, returnString, color, onClick, onEnter, onExit));
		}

		public virtual void RemoveClickable()
		{
			this._entries.Clear();
		}

		protected abstract void RegisterClickable();

		public override void ModifyMesh(VertexHelper vertexHelper)
		{
			this._entries.Clear();
			this.RegisterClickable();
			List<UIVertex> list = HyperTextBase._verticesPool.Get();
			vertexHelper.GetUIVertexStream(list);
			this.Modify(ref list);
			vertexHelper.Clear();
			vertexHelper.AddUIVertexTriangleStream(list);
			HyperTextBase._verticesPool.Release(list);
			if (Application.isPlaying)
			{
				base.StartCoroutine(this.CreateLinkObject());
			}
		}

		protected void Modify(ref List<UIVertex> vertices)
		{
			if (!base.enabled)
			{
				return;
			}
			int count = vertices.Count;
			int i = 0;
			int count2 = this._entries.Count;
			while (i < count2)
			{
				HyperTextBase.ClickableEntry value = this._entries[i];
				value.CharVertices.Clear();
				int j = value.StartIndex;
				int num = value.StartIndex + value.ClickableWord.Length;
				while (j < num)
				{
					int num2 = j * 6;
					if (num2 + 6 > count)
					{
						break;
					}
					char c = this.text.text[j];
					if (c != '\n' && c != '\r')
					{
						Vector2 min = Vector2.one * float.MaxValue;
						Vector2 max = Vector2.one * float.MinValue;
						for (int k = 0; k < 6; k++)
						{
							UIVertex uivertex = vertices[num2 + k];
							Vector3 position = vertices[num2 + k].position;
							if (position.y < min.y)
							{
								min.y = position.y;
							}
							if (position.x < min.x)
							{
								min.x = position.x;
							}
							if (position.y > max.y)
							{
								max.y = position.y;
							}
							if (position.x > max.x)
							{
								max.x = position.x;
							}
							value.CharVertices.Add(uivertex);
							uivertex.position = Vector3.zero;
							vertices[num2 + k] = uivertex;
						}
						value.Rects.Add(new Rect
						{
							min = min,
							max = max
						});
					}
					j++;
				}
				List<Rect> list = new List<Rect>();
				foreach (List<Rect> rects in this.SplitRectsByRow(value.Rects))
				{
					list.Add(this.CalculateAABB(rects));
				}
				value.Rects = list;
				this._entries[i] = value;
				i++;
			}
		}

		private List<List<Rect>> SplitRectsByRow(List<Rect> rects)
		{
			List<List<Rect>> list = new List<List<Rect>>();
			int num = 0;
			int i = 1;
			int count = rects.Count;
			while (i < count)
			{
				if (rects[i].xMin < rects[i - 1].xMin)
				{
					list.Add(rects.GetRange(num, i - num));
					num = i;
				}
				i++;
			}
			if (num < rects.Count)
			{
				list.Add(rects.GetRange(num, rects.Count - num));
			}
			return list;
		}

		private Rect CalculateAABB(List<Rect> rects)
		{
			Vector2 min = Vector2.one * float.MaxValue;
			Vector2 max = Vector2.one * float.MinValue;
			int i = 0;
			int count = rects.Count;
			while (i < count)
			{
				if (rects[i].xMin < min.x)
				{
					min.x = rects[i].xMin;
				}
				if (rects[i].yMin < min.y)
				{
					min.y = rects[i].yMin;
				}
				if (rects[i].xMax > max.x)
				{
					max.x = rects[i].xMax;
				}
				if (rects[i].yMax > max.y)
				{
					max.y = rects[i].yMax;
				}
				i++;
			}
			return new Rect
			{
				min = min,
				max = max
			};
		}

		private IEnumerator CreateLinkObject()
		{
			yield return null;
			if (!base.enabled)
			{
				yield break;
			}
			int i = 0;
			while (i < this._entries.Count)
			{
				HyperTextBase.ClickableEntry entry = this._entries[i];
				bool flag = entry.Rects.Count <= 0;
				Rect rect = this.CalculateAABB(entry.Rects);
				GameObject gameObject;
				if (base.transform.childCount <= i)
				{
					gameObject = new GameObject("clickable");
					gameObject.transform.SetParent(base.transform, false);
					goto IL_FE;
				}
				gameObject = base.transform.GetChild(i).gameObject;
				if (!flag)
				{
					goto IL_FE;
				}
				gameObject.SetActive(false);
				IL_25F:
				i++;
				continue;
				IL_FE:
				gameObject.name = entry.ClickableWord;
				if (!gameObject.activeSelf)
				{
					gameObject.SetActive(true);
				}
				RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
				if (rectTransform == null)
				{
					rectTransform = gameObject.AddComponent<RectTransform>();
				}
				Text text = gameObject.GetComponent<Text>();
				if (text == null)
				{
					text = gameObject.AddComponent<Text>();
					Button button = gameObject.AddComponent<Button>();
					ColorBlock colors = button.colors;
					colors.normalColor = Color.cyan;
					colors.fadeDuration = 0.1f;
					colors.colorMultiplier = 3f;
					button.colors = colors;
					Navigation navigation = button.navigation;
					navigation.mode = Navigation.Mode.None;
					button.navigation = navigation;
				}
				text.text = entry.ClickableWord;
				text.font = this.text.font;
				text.fontSize = this.text.fontSize;
				text.supportRichText = true;
				text.horizontalOverflow = HorizontalWrapMode.Overflow;
				text.verticalOverflow = VerticalWrapMode.Overflow;
				HyperTextBase.LinkObject linkObject = gameObject.GetComponent<HyperTextBase.LinkObject>();
				if (linkObject == null)
				{
					linkObject = gameObject.AddComponent<HyperTextBase.LinkObject>();
				}
				linkObject.entry = entry;
				rectTransform.pivot = Vector2.zero;
				rectTransform.sizeDelta = rect.size;
				rectTransform.localPosition = rect.position;
				goto IL_25F;
			}
			for (int j = this._entries.Count; j < base.transform.childCount; j++)
			{
				base.transform.GetChild(j).gameObject.SetActive(false);
			}
			yield break;
		}

		private Vector3 ToLocalPosition(Vector3 position, Camera camera)
		{
			if (!this.RootCanvas)
			{
				return Vector3.zero;
			}
			if (this.RootCanvas.renderMode == RenderMode.ScreenSpaceOverlay)
			{
				return base.transform.InverseTransformPoint(position);
			}
			Vector2 zero = Vector2.zero;
			RectTransformUtility.ScreenPointToLocalPointInRectangle(this.text.rectTransform, position, camera, out zero);
			return zero;
		}

		public bool IsRaycastLocationValid(Vector2 screenPos, Camera eventCamera)
		{
			Vector3 point = this.ToLocalPosition(screenPos, eventCamera);
			for (int i = 0; i < this._entries.Count; i++)
			{
				for (int j = 0; j < this._entries[i].Rects.Count; j++)
				{
					if (this._entries[i].Rects[j].Contains(point))
					{
						return true;
					}
				}
			}
			return false;
		}

		private Canvas _rootCanvas;

		private Text m_TextComp;

		private const int CHAR_VERTS_NUM = 6;

		private readonly List<HyperTextBase.ClickableEntry> _entries = new List<HyperTextBase.ClickableEntry>();

		private static readonly ObjectPool<List<UIVertex>> _verticesPool = new ObjectPool<List<UIVertex>>(null, delegate(List<UIVertex> l)
		{
			l.Clear();
		});

		public struct ClickableEntry
		{
			public ClickableEntry(string clickableWord, int startIndex, string returnString, Color color, Action<string> onClick, Action<HyperTextBase.ClickableEntry> onEnter, Action<HyperTextBase.ClickableEntry> onExit)
			{
				this.ClickableWord = clickableWord;
				this.StartIndex = startIndex;
				this.ReturnString = returnString;
				this.Color = color;
				this.OnClick = onClick;
				this.OnEnter = onEnter;
				this.OnExit = onExit;
				this.isOverrideColor = true;
				this.Rects = new List<Rect>();
				this.CharVertices = new List<UIVertex>();
			}

			public string ClickableWord;

			public int StartIndex;

			public Color Color;

			public bool isOverrideColor;

			public string ReturnString;

			public Action<string> OnClick;

			public Action<HyperTextBase.ClickableEntry> OnEnter;

			public Action<HyperTextBase.ClickableEntry> OnExit;

			public List<Rect> Rects;

			public List<UIVertex> CharVertices;
		}

		public class LinkObject : BaseMeshEffect, IPointerClickHandler, IPointerEnterHandler, IPointerExitHandler, IEventSystemHandler
		{
			public void OnPointerClick(PointerEventData eventData)
			{
				this.entry.OnClick(this.entry.ReturnString);
			}

			public void OnPointerEnter(PointerEventData eventData)
			{
				this.entry.OnEnter(this.entry);
			}

			public void OnPointerExit(PointerEventData eventData)
			{
				this.entry.OnExit(this.entry);
			}

			public override void ModifyMesh(VertexHelper vertexHelper)
			{
				vertexHelper.Clear();
				List<UIVertex> list = HyperTextBase._verticesPool.Get();
				list.AddRange(this.entry.CharVertices);
				for (int i = 0; i < list.Count; i++)
				{
					UIVertex value = list[i];
					value.position -= base.transform.localPosition;
					list[i] = value;
				}
				vertexHelper.AddUIVertexTriangleStream(list);
				HyperTextBase._verticesPool.Release(list);
			}

			public HyperTextBase.ClickableEntry entry;
		}
	}
}
