﻿﻿using UnityEngine;
using UnityEngine.UI;

namespace AC.Downloads.SpeechBubble
{

	public class SpeechBubbleUI : MonoBehaviour
	{

		#region Variables

		[SerializeField] private RectTransform panelRect = null;
		[SerializeField] private RectTransform containerRect = null;
		[SerializeField] private RectTransform arrowRect = null;
		[SerializeField] private TMPro.TextMeshProUGUI textBox = null;
		[SerializeField] private Canvas canvas = null;
		[SerializeField] private float maxWidth = 350f;
		[SerializeField] private float minWidth = 50f;
		[Range (-0.5f, 0.5f)] public float arrowRelativePosition = 0.25f;
		
		private bool requireLayoutRebuild;

		#endregion


		#region UnityStandards

		private void OnEnable ()
		{
			requireLayoutRebuild = true;
		}


		private void LateUpdate ()
		{
			Menu subsMenu = KickStarter.playerMenus.GetMenuWithCanvas (canvas);
			if (subsMenu == null) return;

			SetMenuScale (subsMenu);
			
			if (arrowRect)
			{
				SetArrowPosition ();
				SetArrowScale (subsMenu);
			}
		}

		#endregion


		#region PrivateFunctions

		private void SetMenuScale (Menu menu)
		{
			float preferredWidth = textBox.GetPreferredValues (textBox.text).x;
			float panelWidth = Mathf.Min (preferredWidth, maxWidth);
			panelWidth = Mathf.Max (panelWidth, minWidth);

			if (panelRect.sizeDelta.x != panelWidth)
			{
				panelRect.sizeDelta = new Vector2 (panelWidth, panelRect.sizeDelta.y);
				KickStarter.playerMenus.UpdateMenuPosition (menu, Vector2.zero);
			}
		}


		private void SetArrowScale (Menu menu)
		{
			Speech speech = menu.speech;
			if (speech == null)
			{
				speech = KickStarter.dialog.GetLatestSpeech ();
			}
			if (speech != null && speech.speaker)
			{
				float speakerScreenX = Camera.main.WorldToScreenPoint (speech.speaker.transform.position).x;
				float arrowScreenX = GetScreenCoordinates (arrowRect).center.x;
				
				if (arrowScreenX < speakerScreenX)
				{
					arrowRect.localScale = new Vector3 (-1f, 1f, 1f);
				}
				else
				{
					arrowRect.localScale = new Vector3 (1f, 1f, 1f);
				}
			}
		}


		private void SetArrowPosition ()
		{
			if (requireLayoutRebuild)
			{
				UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate (panelRect);
				requireLayoutRebuild = false;
			}

			arrowRect.localPosition = containerRect.localPosition
									+ panelRect.localPosition
									+ new Vector3 ((containerRect.sizeDelta.x - arrowRect.sizeDelta.x) * arrowRelativePosition, -containerRect.sizeDelta.y * 0.5f, 0f);
		}


		private Rect GetScreenCoordinates (RectTransform uiElement)
		{
			var worldCorners = new Vector3[4];
			uiElement.GetWorldCorners(worldCorners);
			var result = new Rect(
							worldCorners[0].x,
							worldCorners[0].y,
							worldCorners[2].x - worldCorners[0].x,
							worldCorners[2].y - worldCorners[0].y);
			return result;
		}

		#endregion

	}

}