﻿using System.Collections;
using UnityEngine;

namespace AC
{

	public class GabrielKnightConversations : MonoBehaviour
	{

		#region Variables

		[SerializeField] private NPC npcSpeakingTo = null;
		[SerializeField] private string conversationMenuName = "GK_Conversation";
		[SerializeField] private string[] menusToLock = new string[2] { "InGame", "Subtitles" };
		[SerializeField] private Conversation autoConversation = null;

		private Menu conversationMenu;
		private MenuDialogList dialogList;
		private MenuLabel playerSubs;
		private MenuLabel npcSubs;
		private MenuGraphic playerPortrait;
		private MenuGraphic npcPortrait;

		#endregion


		#region UnityStandards

		private void OnValidate ()
		{
			if (autoConversation == null) autoConversation = GetComponent<Conversation> ();
		}


		private void OnEnable ()
		{
			AssignMenuVars ();

			EventManager.OnBeginActionList += OnBeginActionList;
			EventManager.OnEnterGameState += OnEnterGameState;
			EventManager.OnStartSpeech_Alt += OnStartSpeech_Alt;
			EventManager.OnStopSpeech += OnStopSpeech;
			EventManager.OnStartConversation += OnStartConversation;
			EventManager.OnEndConversation += OnEndConversation;
			EventManager.OnClickConversation += OnClickConversation;
			EventManager.OnSkipSpeech += OnSkipSpeech;
		}


		private void OnDisable ()
		{
			EventManager.OnBeginActionList -= OnBeginActionList;
			EventManager.OnEnterGameState -= OnEnterGameState;
			EventManager.OnStartSpeech_Alt -= OnStartSpeech_Alt;
			EventManager.OnStopSpeech -= OnStopSpeech;
			EventManager.OnStartConversation -= OnStartConversation;
			EventManager.OnEndConversation -= OnEndConversation;
			EventManager.OnClickConversation -= OnClickConversation;
			EventManager.OnSkipSpeech -= OnSkipSpeech;
		}


		private void Start()
		{
			AssignMenuVars();
		}

		#endregion


		#region PublicFunctions

		public void BeginDialogueMode ()
		{
			if (KickStarter.player) playerPortrait.PortraitCharacterOverride = KickStarter.player;
			npcPortrait.PortraitCharacterOverride = npcSpeakingTo;

			if (conversationMenu != null)
			{
				conversationMenu.isLocked = false;

				foreach (string menuToLock in menusToLock)
				{
					Menu menu = PlayerMenus.GetMenuWithName(menuToLock);
					if (menu != null) menu.isLocked = true;
				}
			}
		}


		public void EndDialogueMode ()
		{
			if (conversationMenu != null && !conversationMenu.isLocked)
			{
				conversationMenu.TurnOff ();
				conversationMenu.isLocked = true;

				foreach (string menuToLock in menusToLock)
				{
					Menu menu = PlayerMenus.GetMenuWithName (menuToLock);
					if (menu != null) menu.isLocked = false;
				}
			}
		}

		#endregion


		#region CustomEvents

		private void OnBeginActionList (ActionList actionList, ActionListAsset actionListAsset, int startingIndex, bool isSkipping)
		{
			if (ActionListReferencesConversation (actionList))
			{
				BeginDialogueMode ();
			}
		}


		private void OnEnterGameState (GameState gameState)
		{
			if (autoConversation && gameState == GameState.Normal)
			{
				EndDialogueMode ();
			}
		}


		private void OnStartSpeech_Alt (Speech speech)
		{
			if (speech.GetSpeakingCharacter () == KickStarter.player)
			{
				playerSubs.SetSpeech (speech);
			}
			else if (speech.GetSpeakingCharacter () == npcSpeakingTo)
			{
				npcSubs.SetSpeech (speech);
			}
		}


		private void OnStopSpeech (Char speakingCharacter)
		{
			if (speakingCharacter == KickStarter.player)
			{
				playerSubs.SetSpeech (null);
			}
			else if (speakingCharacter == npcSpeakingTo)
			{
				npcSubs.SetSpeech (null);
			}
		}


		private void OnClickConversation (Conversation conversation, int optionID)
		{
			dialogList.IsVisible = false;
		}


		private void OnStartConversation (Conversation conversation)
		{
			if (autoConversation == null || autoConversation == conversation)
			{
				dialogList.IsVisible = true;
				dialogList.OverrideConversation = conversation;
				dialogList.ParentMenu.Recalculate();
			}
		}


		private void OnEndConversation (Conversation conversation)
		{
			if (autoConversation == null || autoConversation == conversation)
			{
				dialogList.IsVisible = true;
			}
		}


		private void OnSkipSpeech (Speech speech, bool justCompletingScroll)
		{
			StartCoroutine (BlockUIClicks ());
		}

		#endregion


		#region PrivateFunctions

		private IEnumerator BlockUIClicks ()
		{
			var eventSystem = KickStarter.playerMenus.EventSystem;
			if (eventSystem)
			{
				eventSystem.enabled = false;
				yield return null;
				eventSystem.enabled = true;
			}
		}


		private void AssignMenuVars ()
		{
			conversationMenu = PlayerMenus.GetMenuWithName (conversationMenuName);
			if (conversationMenu == null)
			{
				ACDebug.LogWarning ("Cannot find Menu named " + conversationMenuName);
				return;
			}
			dialogList = conversationMenu.GetElementWithName ("DialogueList") as MenuDialogList;

			playerSubs = conversationMenu.GetElementWithName ("PlayerSubs") as MenuLabel;
			playerSubs.SetSpeech (null);
			npcSubs = conversationMenu.GetElementWithName ("NPCSubs") as MenuLabel;
			npcSubs.SetSpeech (null);

			playerPortrait = conversationMenu.GetElementWithName ("PlayerPortrait") as MenuGraphic;
			npcPortrait = conversationMenu.GetElementWithName ("NPCPortrait") as MenuGraphic;
		}


		private bool ActionListReferencesConversation (ActionList actionList)
		{
			if (autoConversation == null) return false;

			foreach (Action action in actionList.actions)
			{
				ActionConversation actionConversation = action as ActionConversation;
				if (actionConversation != null && actionConversation.conversation == autoConversation)
				{
					return true;
				}
			}
			return false;
		}

		#endregion
		
	}

}