/**
 * Tento skript ma na starost spravny chod pohybliveho menu kategorii a podkategorii.
 */
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
/**
 * Author:			Karel Zavrel
 * 
 * Thesis:			An interactive application for development of creativity
 * Application:		Little Builder
 */
public class ScrollRectScript : MonoBehaviour {
	/**
	 * soukrome promenne pro panel kategorii:
	 * 	- panel kategorii
	 * 	- pohyblivy panel kategorii
	 * 	- pole se vsemi tlacitky znazornujicimi jednotlive kategorie
	 * 	- stred panelu, se kterym je porovnavana vzdalenost vsech prvku
	 * 	- pocet tlacitek, kategorii
	 */
	private GameObject categoryPanel;
	private RectTransform categoryScrollPanel;
	private Button[] categoryButtons;
	private RectTransform categoryCenter;
	private int countOfCategoryButtons = 10;
	/**
	 * promenne k posuvniku kostek, aktualizuji se pri otevreni kazde kategorie:
	 * 	- panel pro podkategorie
	 * 	- posuvny panel s jednotlivymi kostkami
	 * 	- vsechny posuvne panely jednotlivych podkategorii
	 * 	- aktivni sada tlacitek
	 * 	- nazvy jednotlivych podkategorii
	 * 	- pocty tlacitek jednotlivych podkategorii
	 * 	- aktivni stred pro srovnani vzdalenosti
	 */
	private GameObject bricksPanel;
	private RectTransform activeBrickScrollPanel;
	private GameObject[] scrollPanels;
	private Button[] activeBrickButtons;
	private string[] namesOfSubcategories = new string[]{"Bricks_1_", "Bricks_2_", "LowerBricks_1_", "LowerBricks_2_", "LowerBricks_4_", "LowerBricks_6_", "BevelledBricks_2_", "BevelledBricks_3_", "BevelledBricks_4_", "BevelledCornerBricks_2_"};
	private int[] countsOfButtonsOfEachSubcategory = new int[]{9, 8, 9, 8, 6, 5, 5, 5, 5, 3};
	private int[] countsOfCleats = new int[]{1, 2, 3, 4, 6, 8, 10, 12, 16};
	private RectTransform activeBrickCenter;
	/**
	 * promenne vztahujici se k obema posuvnikum, ktere se aktualizuji pri kazde zmene:
	 * 	- vsechny vzdalenosti tlacitek od stredu
	 * 	- pomocna promenna pro detekci, zda je posunovan panel
	 * 	- vzdalenost mezi dvema sousednimi tlacitky
	 * 	- index nejblizsiho tlacitka ke stredu
	 */
	private float[] distancesFromCenter;
	private bool isDragging = false;
	private int distanceBetweenTwoButtons;
	private int indexOfTheNearestButton;
	/**
	 * promenne, na ktere se zmena aplikuje, prereferencovavaji se na nove (aktualni) objekty:
	 * 	- stred, ke kteremu se pocitaji zmeny
	 * 	- aktualni skrolovaci panel
	 * 	- tlacitka, ktera jsou prave zobrazena
	 */
	private RectTransform actualCenter;
	private RectTransform actualScrollPanel;
	private Button[] actualButtons;

	/**
	 * funkce pro inicializaci vsech promennych
	 */
	void Start() {
		inicializeCategoryVariables ();			// inicializuje promenne posuvniku kategorii
		inicializeSubcategoriesVariables ();	// inicializuje promenne posuvniku jednotlivych podkategorii
		/**
		 * nejprve je aktivni posuvnik kategorii
		 */
		reinicializeActualVariables (categoryCenter, categoryButtons, categoryScrollPanel);
	}
	/**
	 * funkce pro inicializaci promennych tykajicich se posuvniku kategorii
	 */
	private void inicializeCategoryVariables(){
		categoryPanel = GameObject.Find ("CategoryPanel");
		categoryScrollPanel = GameObject.Find ("CategoryScrollPanel").GetComponent<RectTransform> ();
		categoryButtons = fillButtonsArray (countOfCategoryButtons, "CategoryButton_");
		categoryCenter = GameObject.Find ("CategoryScrollPanelCenter").GetComponent<RectTransform> ();
	}
	/**
	 * funkce pro naplneni pole tlacitek
	 * 	-	nutno predat pocet tlacitek a nazev, dle ktereho se hledaji
	 */
	private Button[] fillButtonsArray(int countOfButtons, string nameOfButtons){
		Button[] buttonsArray = new Button[countOfButtons];
		string s;
		for (int i = 0; i < countOfButtons; i++) {
			if (categoryPanel.activeSelf) {
				s = nameOfButtons + (i + 1).ToString ();
			} else {
				switch (nameOfButtons) {
					case "Bricks_1_Button_":
					case "LowerBricks_1_Button_":
					case "BevelledBricks_2_Button_":
					case "BevelledBricks_3_Button_":
					case "BevelledBricks_4_Button_":
						s = nameOfButtons + countsOfCleats [i].ToString ();
						break;
					case "Bricks_2_Button_":
					case "LowerBricks_2_Button_":
						s = nameOfButtons + countsOfCleats [i + 1].ToString ();
						break;
					case "LowerBricks_4_Button_":
						s = nameOfButtons + countsOfCleats [i + 3].ToString ();
						break;
					case "LowerBricks_6_Button_":
						s = nameOfButtons + countsOfCleats [i + 4].ToString ();
						break;
					case "BevelledCornerBricks_2_Button_":
						s = nameOfButtons + countsOfCleats [i + 1].ToString ();
						break;
					default:
						s = nameOfButtons + "4";
						break;
				}
			}
			buttonsArray [i] = GameObject.Find (s).GetComponent<Button> ();
		}
		return buttonsArray;
	}
	/**
	 * funkce pro inicializaci promennych tykajicich se posuvniku jednotlivych podkategorii
	 */
	private void inicializeSubcategoriesVariables(){
		bricksPanel = GameObject.Find ("BricksPanel");
		scrollPanels = fillSubcategoryPanelsArray (namesOfSubcategories);
		deactivateAllSubcategoryScrollPanels ();
		bricksPanel.SetActive (false);
	}
	/**
	 * funkce pro naplneni pole panelu jednotlivych podkategorii
	 * 	-	nutno predat pole nazvu jednotlivych kategorii
	 */
	private GameObject[] fillSubcategoryPanelsArray(string[] nameOfPanels){
		GameObject[] panelsArray = new GameObject[nameOfPanels.Length];
		string s;
		for (int i = 0; i < nameOfPanels.Length; i++) {
			s = nameOfPanels[i] + "Panel";
			panelsArray[i] = GameObject.Find(s);
		}
		return panelsArray;
	}
	/**
	 * funkce, ktera deaktivuje vsechny skrolovaci panely podkategorii
	 */
	private void deactivateAllSubcategoryScrollPanels(){
		for (int i = 0; i < scrollPanels.Length; i++) {
			if(scrollPanels[i].activeSelf){
				scrollPanels[i].SetActive(false);
			}
		}
	}
	/**
	 * prenastaveni promennych na aktualni, ktere jsou zobrazeny a se kterymi je interagovano
	 * 	-	pole vzdalenosti, tlacitka, stred
	 */
	private void reinicializeActualVariables(RectTransform center, Button[] buttons, RectTransform panel){
		actualCenter = center;
		actualButtons = buttons;
		actualScrollPanel = panel;
		distancesFromCenter = new float[buttons.Length];
		distanceBetweenTwoButtons = (int)Mathf.Abs (buttons [1].GetComponent<RectTransform> ().anchoredPosition.y - buttons [0].GetComponent<RectTransform> ().anchoredPosition.y);
	}
	/**
	 * funkce volana v kazdem framu
	 */
	void Update(){
		for (int i = 0; i < actualButtons.Length; i++) {
			distancesFromCenter[i] = Mathf.Abs(actualCenter.transform.position.y - actualButtons[i].transform.position.y);
		}
		float minDistance = Mathf.Min (distancesFromCenter);
		for (int a = 0; a < actualButtons.Length; a++) {
			if (minDistance == distancesFromCenter[a]) {
				indexOfTheNearestButton = a;
			}
		}
		if (!isDragging) {
			lerpToButton(indexOfTheNearestButton * -distanceBetweenTwoButtons);
		}
	}
	/**
	 * funkce pro pomale ustaleni posuvniku po skonceni pohybu
	 */
	private void lerpToButton(int position){
		float newY = Mathf.Lerp (actualScrollPanel.anchoredPosition.y, position, Time.deltaTime * 10.0f);
		Vector2 newPosition = new Vector2 (actualScrollPanel.anchoredPosition.x, newY);
		actualScrollPanel.anchoredPosition = newPosition;
	}
	/**
	 * funkce pro nastaveni isDragging na true pri započeti tazeni posuvniku
	 */
	public void StartDrag(){
		isDragging = true;
		InnerStoringScript.setIsRotationPermitted (false);
		InnerStoringScript.setIsScalePermitted (false);
	}
	/**
	 * funkce pro nastaveni isDragging na false pri skonceni tazeni posuvniku
	 */
	public void EndDrag(){
		isDragging = false;
		if (bricksPanel.activeSelf) {
			InnerStoringScript.setIsMinimapImageVisible (false);
			InnerStoringScript.setButtonForDetailObject (actualButtons [indexOfTheNearestButton].name);
		}
		InnerStoringScript.setIsRotationPermitted (true);
		InnerStoringScript.setIsScalePermitted (true);
	}
	/**
	 * funkce, ktera zavre posuvnik kategorii a otevre konkretni posuvnik podkategorie
	 */
	public void openBrickPanel(int index){
		categoryPanel.SetActive (false);
		bricksPanel.SetActive (true);
		scrollPanels [index].SetActive (true);
		string scrollPanelName = namesOfSubcategories [index] + "ScrollPanel";
		activeBrickScrollPanel = GameObject.Find (scrollPanelName).GetComponent<RectTransform> ();
		string centerName = namesOfSubcategories [index] + "ScrollPanelCenter";
		activeBrickCenter = GameObject.Find (centerName).GetComponent<RectTransform> ();
		string subcategoryName = namesOfSubcategories [index] + "Button_";
		activeBrickButtons = fillButtonsArray (countsOfButtonsOfEachSubcategory [index], subcategoryName);
		reinicializeActualVariables (activeBrickCenter, activeBrickButtons, activeBrickScrollPanel);
	}
	/**
	 * funkce, ktera zavre posuvnik podkategorie a otevre posuvnik kategorii
	 */
	public void openCategoryPanel(){
		deactivateAllSubcategoryScrollPanels ();
		bricksPanel.SetActive (false);
		categoryPanel.SetActive (true);
		reinicializeActualVariables (categoryCenter, categoryButtons, categoryScrollPanel);
	}
}