using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public abstract class LaunchManagement {
	private static Transform allTemplates;
	private static List<Tuple<GameObject, GameObject>> panelsAndButtons; //where to clone the new UI, depending on their tab

	public static void init() {
		allTemplates = GameObject.Find("Templates/Launch&Command").transform;

		panelsAndButtons = new List<Tuple<GameObject, GameObject>>();
		panelsAndButtons.Add(getPanel("InFlight"));
		panelsAndButtons.Add(getPanel("Ready"));
		panelsAndButtons.Add(getPanel("Deck"));
		panelsAndButtons.Add(getPanel("Storage"));
		panelsAndButtons.Add(getPanel("Command"));

		GameController.GUI.SetActive(false);
	}

	private static Tuple<GameObject, GameObject> getPanel(string name) {
		return new Tuple<GameObject, GameObject>(GameObject.Find("Canvas/GUI/Launch&Command/" + name), GameObject.Find("Canvas/GUI/Launch&Command/Tabs/" + name));
	}

	public static void constructLaunchAndCommand(DeployedUnit selectedUnit) {
		foreach(Tuple<GameObject, GameObject> tab in panelsAndButtons) {
			GameController.deleteAllChildren(tab._1.transform);
			tab._2.SetActive(false);
		}

		//InFlight
		GameController.deleteAllChildren(panelsAndButtons[0]._1.transform);
		panelsAndButtons[0]._1.GetComponent<DeployedListBehaviour>().units = new List<DeployedUnit>();
		reconstructInFlight(selectedUnit, panelsAndButtons[0]._1.GetComponent<DeployedListBehaviour>());

		//Ready
		GameController.deleteAllChildren(panelsAndButtons[1]._1.transform);
		panelsAndButtons[1]._1.GetComponent<UnitListBehaviour>().units = new List<StoredUnit>();
		reconstructReadyOrDeck(selectedUnit, panelsAndButtons[1]._1.GetComponent<UnitListBehaviour>(), 1);

		//Deck
		GameController.deleteAllChildren(panelsAndButtons[2]._1.transform);
		panelsAndButtons[2]._1.GetComponent<UnitListBehaviour>().units = new List<StoredUnit>();
		reconstructReadyOrDeck(selectedUnit, panelsAndButtons[2]._1.GetComponent<UnitListBehaviour>(), 2);

		//Storage
		GameController.deleteAllChildren(panelsAndButtons[3]._1.transform);
		GameObject launch = allTemplates.transform.Find("Multiple").gameObject;
		int count = 0;
		foreach(Class launched in selectedUnit.getClass().getLaunchedClasses()) {
			panelsAndButtons[3]._2.SetActive(true);

			GameObject clone = GameObject.Instantiate(launch, panelsAndButtons[3]._1.transform);

			clone.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 0);
			clone.transform.localPosition = new Vector3(0, -count * clone.GetComponent<RectTransform>().rect.height);

			clone.transform.Find("Name").GetComponent<Text>().text =  launched.getName();
			//TODO : change image

			clone.transform.Find("Loadout").GetComponent<Dropdown>().ClearOptions();
			foreach(Loadout loadout in launched.getLoadouts()) {
				clone.transform.Find("Loadout").GetComponent<Dropdown>().options.Add(new Dropdown.OptionData(loadout.getName()));
			}
			clone.transform.Find("Loadout").GetComponent<Dropdown>().RefreshShownValue();

			clone.GetComponent<LaunchBehaviour>().launchedClass = launched;
			clone.GetComponent<LaunchBehaviour>().loadout = Loadout.empty();

			count++;
		}

		//Command
		panelsAndButtons[4]._2.SetActive(false);
		GameController.deleteAllChildren(panelsAndButtons[4]._1.transform);
		if (selectedUnit.getClass().getClassType() == ClassType.Helicopter) {
			panelsAndButtons[4]._2.SetActive(true);

			GameObject land = allTemplates.transform.Find("Land").gameObject;
			GameObject clone = GameObject.Instantiate(land, panelsAndButtons[4]._1.transform);

			clone.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 0);
			clone.transform.localPosition = new Vector3(0, 0);
		}

		updateTabs();
	}

	private static void updateTabs() {
		bool needToChangeTab = false;
		foreach(Tuple<GameObject, GameObject> tab in panelsAndButtons) {
			if (!tab._2.activeSelf) {
				OnOffButton button = tab._2.GetComponent<OnOffButton>();

				if (button.state) {
					needToChangeTab = true;
					break;
				}
			}
		}

		if (needToChangeTab) {
			foreach(Tuple<GameObject, GameObject> tab in panelsAndButtons) {
				if (tab._2.activeSelf) {
					OnOffButton button = tab._2.GetComponent<OnOffButton>();
					button.click();
					break;
				}
			}
		}
	}

	private static void reconstructInFlight(DeployedUnit selectedUnit, DeployedListBehaviour currentList) {
		List<DeployedUnit> units = selectedUnit.getBirds();

		if (new HashSet<DeployedUnit>(units).SetEquals(currentList.units)) { //no change
			return;
		}

		panelsAndButtons[0]._2.SetActive(false);

		currentList.units = new List<DeployedUnit>(units);
		GameObject inFlight = allTemplates.transform.Find("InFlight").gameObject;

		GameController.deleteAllChildren(panelsAndButtons[0]._1.transform);
		int count = 0;
		foreach(DeployedUnit unit in currentList.units) {
			panelsAndButtons[0]._2.SetActive(true);

			GameObject clone = GameObject.Instantiate(inFlight, panelsAndButtons[0]._1.transform);

			clone.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 0);
			clone.transform.localPosition = new Vector3(0, -count * clone.GetComponent<RectTransform>().rect.height);

			clone.transform.Find("Name").GetComponent<Text>().text =  unit.getClass().getName();

			count++;
		}

		updateTabs();
	}

	private static void reconstructReadyOrDeck(DeployedUnit selectedUnit, UnitListBehaviour currentList, int index) {
		List<StoredUnit> units = index == 1 ? selectedUnit.getUnitsReady() : selectedUnit.getUnitsOnDeck();

		if (new HashSet<StoredUnit>(units).SetEquals(currentList.units)) { //no change
			return;
		}

		panelsAndButtons[index]._2.SetActive(false);

		currentList.units = new List<StoredUnit>(units);;
		GameObject single = allTemplates.transform.Find("Single").gameObject;

		GameController.deleteAllChildren(panelsAndButtons[index]._1.transform);
		int count = 0;
		foreach(StoredUnit unit in currentList.units) {
			panelsAndButtons[index]._2.SetActive(true);

			GameObject clone = GameObject.Instantiate(single, panelsAndButtons[index]._1.transform);

			clone.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 0);
			clone.transform.localPosition = new Vector3(0, -count * clone.GetComponent<RectTransform>().rect.height);

			clone.transform.Find("Name").GetComponent<Text>().text =  unit.getClass().getName();

			clone.GetComponent<SingleLaunchBehaviour>().stored = unit;

			count++;
		}

		updateTabs();
	}

	public static void updateLaunchAndCommand(DeployedUnit selectedUnit) {
		reconstructInFlight(selectedUnit, panelsAndButtons[0]._1.GetComponent<DeployedListBehaviour>());
		reconstructReadyOrDeck(selectedUnit, panelsAndButtons[1]._1.GetComponent<UnitListBehaviour>(), 1);
		reconstructReadyOrDeck(selectedUnit, panelsAndButtons[2]._1.GetComponent<UnitListBehaviour>(), 2);

		//Ready
		if (panelsAndButtons[1]._1.activeSelf) {
			foreach(Transform child in panelsAndButtons[1]._1.transform) {
				SingleLaunchBehaviour behaviour = child.gameObject.GetComponent<SingleLaunchBehaviour>();

				child.Find("Preparing").gameObject.SetActive(false);

				child.Find("Loadout/Text").GetComponent<Text>().text = behaviour.stored.getCurrentLoadout() == null ? "Empty" : behaviour.stored.getCurrentLoadout().getName();
			}
		}

		//Deck
		if (panelsAndButtons[2]._1.activeSelf) {
			foreach(Transform child in panelsAndButtons[2]._1.transform) {
				SingleLaunchBehaviour behaviour = child.gameObject.GetComponent<SingleLaunchBehaviour>();

				child.Find("Launch").GetComponent<Button>().interactable = false;

				child.Find("Preparing").gameObject.SetActive(behaviour.stored.isBeingLoaded() && (Time.frameCount % 30) < 15);

				child.Find("Loadout/Text").GetComponent<Text>().text = behaviour.stored.getCurrentLoadout() == null ? "Empty" : behaviour.stored.getCurrentLoadout().getName();
			}
		}

		//Storage
		if (panelsAndButtons[3]._1.activeSelf) {
			foreach(Transform child in panelsAndButtons[3]._1.transform) {
				LaunchBehaviour behaviour = child.gameObject.GetComponent<LaunchBehaviour>();

				int left = selectedUnit.getNumberInStorage(behaviour.launchedClass);

				child.Find("Left/Text").gameObject.GetComponent<Text>().text = "LEFT : " + left;
				behaviour.max = left;
				behaviour.currentNumber = Mathf.Max(Mathf.Min(behaviour.currentNumber, behaviour.max), 0);

				string canPrepareMessage = selectedUnit.canPrepareMessage(behaviour.launchedClass, behaviour.currentNumber, behaviour.loadout);

				child.Find("Stepup").GetComponent<Button>().interactable = (canPrepareMessage == "");
				child.Find("Stepup").GetComponent<ToolTip>().text = canPrepareMessage;

				child.Find("Number/Display/Text").GetComponent<Text>().text = behaviour.currentNumber + "";
				child.Find("Number/-").GetComponent<Button>().interactable = (behaviour.currentNumber > 1);
				child.Find("Number/+").GetComponent<Button>().interactable = (behaviour.currentNumber < left);

				//child.Find("Launching").gameObject.SetActive(selectedUnit.isLaunching(behaviour.launchedClass) && (Time.frameCount % 30) < 15);
				//child.Find("Preparing").gameObject.SetActive(selectedUnit.isPreparing(behaviour.launchedClass) && (Time.frameCount % 30) >= 15);

				int loadoutIndex = child.Find("Loadout").gameObject.GetComponent<Dropdown>().value;
				behaviour.loadout = behaviour.launchedClass.getLoadout(loadoutIndex);
			}
		}
	}
}
