﻿using UnityEngine;
using System.Collections.Generic;
using Hover.Cast.Items;
using Hover.Common.Items;
using Hover.Common.Items.Types;
using Configurator.Menu;
using Configurator.Utils;
using Configurator.Service;
using Configurator.Service.RedoUndo;
using Configurator.Behaviour;

namespace Configurator.Menu.Hand.Label
{
	public class LabelTextSelector : HovercastItemListener<ISelectorItem>
	{
		public Subassembly Subassembly { get; set; }

		public HovercastItem ParentItem { get; set; }

		private Stack<string> selectedTexts;

		private IObjectService objectService;

		private ISoundService soundService;

		private IRedoUndoService redoUndoService;

		protected override void Setup ()
		{
			ObjectUtils.RequireNonNull (Subassembly);
			ObjectUtils.RequireNonNull (ParentItem);

			selectedTexts = new Stack<string> ();

			objectService = Services.ObjectService;
			soundService = Services.SoundService;
			redoUndoService = Services.RedoUndoService;

			transform.SetParent (ParentItem.transform, worldPositionStays: false);

			Item.OnSelected += SelectedHandler;
		}

		protected override void BroadcastInitialValue ()
		{
			string label = GetLabel ();
			if (label.Length > 0) {
				InputFinishedHandler (label, objectService.Keyboard);
			}
		}

		private void SelectedHandler (ISelectableItem item)
		{
			soundService.SlideSound.Play ();

			Keyboard keyboard = objectService.Keyboard;
			keyboard.OnInputFinished += InputFinishedHandler;

			keyboard.Open (GetLabel ());
		}

		private void InputFinishedHandler (string text, Keyboard keyboard)
		{
			keyboard.OnInputFinished -= InputFinishedHandler;
			SetLabel (text);

			if (selectedTexts.Count == 0 || !selectedTexts.Peek ().Equals (text)) {
				selectedTexts.Push (text);

				redoUndoService.Add (
					() => {
						selectedTexts.Push (text);
						SetLabel (text);
					}, 
					() => {
						selectedTexts.Pop ();
						if (selectedTexts.Count > 0) {
							SetLabel (selectedTexts.Peek ());
						} else {
							SetLabel ("");
						}
					}
				);
			}
		}

		private string GetLabel ()
		{
			foreach (var module in Subassembly.Modules) {
				if (module.Config.Labeled) {
					return module.Config.LabelConfig.Text;
				}
			}

			return "";
		}

		private void SetLabel (string text)
		{
			foreach (var module in Subassembly.Modules) {
				if (module.Config.Labeled) {
					module.SetLabel (text);
				}
			}
		}
	}
}