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

public class GameManager : Singleton<GameManager> {

	// Prefabrykat używany do tworzenia statku, miejsce w którym należy
	// umieścić statek na początku gry oraz bieżący obiekt statku
	public GameObject shipPrefab;
	public Transform shipStartPosition;
	public GameObject currentShip {get; private set;}

	// Prefabrykat używany do tworzenia stacji kosmicznej, miejsce w którym należy
	// umieścić stację na początku gry oraz bieżący obiekt stacji
	public GameObject spaceStationPrefab;
	public Transform spaceStationStartPosition;
	public GameObject currentSpaceStation {get; private set;}

	// Skrypt przesuwający kamerę za wskazanym obiektem
	public SmoothFollow cameraFollow;

	// Granice przestrzeni
	public Boundary boundary;

	// Pojemniki grupujące różne elementy interfejsu użytkownika
	public GameObject inGameUI;
	public GameObject pausedUI;
	public GameObject gameOverUI;
	public GameObject mainMenuUI;

	// Interfejs użytkownika ostrzegający gracza, gdy ten zbliży się
	// do granicy dostępnego obszaru przestrzeni
	public GameObject warningUI;

	// Czy aktualnie trwa rozgrywka?
	public bool gameIsPlaying {get; private set;}

	// Obiekt odpowiedzialny za tworzenie asteroid 
	public AsteroidSpawner asteroidSpawner;

	// Czy gra aktualnie jest zatrzymana, czy nie?
	public bool paused;

	// Metoda wyświetla menu główne w momencie uruchomienia gry
	void Start() {
		ShowMainMenu();
	}

	// Metoda wyświetla pojemnik z elementami interfejsu użytkownika 
	// i ukrywa wszystkie inne
	void ShowUI(GameObject newUI) {

		// Tworzymy listę wszystkich pojemników z elementami interfejsu użytkownika
		GameObject[] allUI = {inGameUI, pausedUI, gameOverUI, mainMenuUI};

		// Ukrywamy je wszystkie
		foreach (GameObject UIToHide in allUI) {
			UIToHide.SetActive(false);
		}

		// A następnie wyświetlamy wskazany z pojemników
		newUI.SetActive(true);
	}

	public void ShowMainMenu() {
		ShowUI(mainMenuUI);

		// Podczas uruchamiania gry rozgrywka nie została jeszcze rozpoczęta
		gameIsPlaying = false;

		// Nie tworzymy także żadnych asteroid
		asteroidSpawner.spawnAsteroids = false;
	}


	// Ta metoda jest wywoływana po dotknięciu przycisku Nowa gra
	public void StartGame() {
		// Wyświetlamy interfejs użytkownika do prowadzenia rozgrywki
		ShowUI(inGameUI);

		// Teraz już trwa rozgrywka
		gameIsPlaying = true;

		// Jeśli istnieje statek, to usuwamy go
		if (currentShip != null) {
			Destroy(currentShip);
		}

		// To samo robimy ze stacją kosmiczną
		if (currentSpaceStation != null) {
			Destroy(currentSpaceStation);
		}

		// Tworzymy nowy statek i umieszczamy go w punkcie początkowym
		currentShip = Instantiate(shipPrefab);
		currentShip.transform.position = shipStartPosition.position;
		currentShip.transform.rotation = shipStartPosition.rotation;

		// Podobnie robimy ze stacją kosmiczną
		currentSpaceStation = Instantiate(spaceStationPrefab);

		currentSpaceStation.transform.position = 
			spaceStationStartPosition.position;

		currentSpaceStation.transform.rotation = 
			spaceStationStartPosition.rotation;

		// Konfigurujemy skrypt, dzięki któremu kamera będzie podążać za statkiem
		cameraFollow.target = currentShip.transform;

		// Rozpoczynamy generowanie asteroid
		asteroidSpawner.spawnAsteroids = true;

		// I informujemy, że należy je wysyłać w kierunku stacji kosmicznej
		asteroidSpawner.target = currentSpaceStation.transform;
	}


	// Ta metoda jest wywoływana przez obiekty, których zniszczenie powoduje
	// zakończenie rozgrywki
	public void GameOver() {
		// Wyświetlamy ekran końcowy
		ShowUI(gameOverUI);

		// Rozgrywka została zakończona
		gameIsPlaying = false;

		// Usuwamy statek oraz stację kosmiczną
		if (currentShip != null)
			Destroy (currentShip);

		if (currentSpaceStation != null)
			Destroy (currentSpaceStation);

		// Jeśli obiekt Warning UI jest widoczny, to go ukrywamy
		warningUI.SetActive(false);

		// Kończymy generowanie asteroid
		asteroidSpawner.spawnAsteroids = false;

		// I usuwamy wszystkie asteroidy, które pozostały w grze
		asteroidSpawner.DestroyAllAsteroids();
	}


	// Metoda jest wywoływana po dotknięciu przycisków pauzy i kontynuowania gry 
	public void SetPaused(bool paused) {

		// Zmieniamy wyświetlany interfejs użytkownika
		inGameUI.SetActive(!paused);
		pausedUI.SetActive(paused);

		// Jeśli gra jest wstrzymana
		if (paused) {
			// Zatrzymujemy upływ czasu
			Time.timeScale = 0.0f;
		} else {
			// Wznawiamy upływ czasu
			Time.timeScale = 1.0f;
		}
	}

	public void Update() {

		// Jeśli nie ma statku, to kończymy
		if (currentShip == null)
			return;

		// Jeśli statek znajduje się poza obszarem sfery wyznaczonej przez
		// destroyRadius, gra zostaje zakończona. Jeśli statek znajdzie się
		// wewnątrz sfery o promieniu destroyRadius lecz poza sferą o promieniu
		// warningRadius, to wyświetlamy obiekt Warning UI. Jeśli statek znajduje 
		// się wewnątrz obu sfer, obiekt Warning UI nie jest wyświetlany.

		float distance = 
			(currentShip.transform.position 
				- boundary.transform.position).magnitude;

		if (distance > boundary.destroyRadius) {
			// Statek wyleciał poza sferę zniszczenia (destroyRadius), grę należy zakończyć
			GameOver();
		} else if (distance > boundary.warningRadius) {
			// Statek wyleciał poza sferę ostrzegawczą (warningRadius), należy 
			// wyświetlić ostrzegawczy interfejs użytkownika (Warning UI)
			warningUI.SetActive(true);
		} else {
			// Statek znajduje się wewnątrz sfery ostrzegawczej, więc nie należy
			// wyświetlać ostrzegawczego interfejsu użytkownika
			warningUI.SetActive(false);
		}

	}

}
