using UnityEngine;
using System.Collections;

public class GameFlow : MonoBehaviour
{
    public GameMode Actual_State = GameMode.Spawning;

	public PlayerManager player1,player2;

    private float timer_start;
    //tempo in cui è iniziata la fase in corso del round

    private float timer_last_spawn;
    //tempo in cui si è verificato l'ultimo spawn

    public float timer_spawning_mode = 5.0f;
    //Quanto dura la fase di spawning
    public float timer_curse_mode = 5.0f;
    // Quanto dura la fase di curse
    public float timer_evocation_mode = 5.0f;
    //Quanto dura la fase di spawning
    public float timer_uncurse_mode = 5.0f;
    // Quanto dura la fase di uncurse
    public float timer_mortality_mode = 5.0f;
    //Quanto dura la fase di spawning
	public float timer_winning_mode = 5.0f;

    public float timer_spawn = 5.0f;
    // Mentre si è nella prima fase del round, ogni quanto viene spawnato un oggetto nuovo

    public int bonus_spawn_first_stage = 2;
    // Numero di spawn addizionali, si verifica solo una volta all'inizio della prima fase

    public float increaseCurse = 5.0f;

	public TextMesh textScreen;

    public int actual_spawn_second_stage = 4;
    // numero di oggetti spawnati nella seconda fase

    public float arena_width;
    public float arena_height;

    public MagicTool Tool;
    private MagicTool tool1;

	public Ghost ghost;
	private Ghost ghost1, ghost2;

    private static GameFlow instance = null;

	private bool changeMode=true;

    private GameObject[] tools;

    public Transform spawningPoint1;
    public Transform spawningPoint2;

    private int contRound = 0;

    public AudioSource audioSource;
    public AudioClip clip1;
    public AudioClip clip2;

    public TutorialPanel instructionsUncurse;
    public TutorialPanel instructionsEndRound;
    public bool firstRound = true;
    public WinningPanel winningGameText;

    /*
    public AudioSource audioSounds;
    public AudioClip endGameClip;
    public AudioClip evocationClip;
    public AudioClip playerSpawnClip;
    */

    public GameMode CurrentState
    {
        get { return Actual_State; }
        set
        {
            Actual_State = value;
            initMode(Actual_State);
        }
    }

    void Awake ()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(instance.gameObject);
            instance = this;
        }
    }

	void Start ()
    {
        Actual_State = GameMode.GameStart;//GameMode.Spawning;
		changeMode = true;
        timer_start = Time.time;
        timer_last_spawn = timer_start;
        tools = GameObject.FindGameObjectsWithTag("MagicTool");
    }


	private GameMode step(GameMode mode){
		switch (mode) {
            case GameMode.GameStart:
                return GameMode.GameStart;
		case  GameMode.Spawning:
			if (Time.time >= timer_spawning_mode + timer_start) {
				SpawnPlayers ();
				return GameMode.Curse;
			}
			return GameMode.Spawning;
		case  GameMode.Curse:
			UIManager.getInstance ().UpdateTimer (Time.time - timer_start, timer_curse_mode);
			if (Time.time >= timer_start + timer_curse_mode) {
				tools = GameObject.FindGameObjectsWithTag ("MagicTool");
				for (int i = 0; i < tools.Length; i++) {
					tools [i].Recycle ();
				}
				return GameMode.InstructionsUnCurse;
			} 

			if (Time.time >= timer_last_spawn + timer_spawn) {
				timer_last_spawn = Time.time;
				this.Spawn ();
			}
			return GameMode.Curse;
            case GameMode.InstructionsUnCurse:
                if (contRound == 1)
                {
                    if (!instructionsUncurse.gameObject.activeSelf)
                        instructionsUncurse.gameObject.SetActive(true);
                    return GameMode.InstructionsUnCurse;
                }
                else
                    return GameMode.Evocation;
		case  GameMode.Evocation:
			if (Time.time >= timer_evocation_mode + timer_start)
			{
				return GameMode.UnCurse;
			}
			return GameMode.Evocation;
		case  GameMode.UnCurse:
			UIManager.getInstance ().UpdateTimer (Time.time - timer_start, timer_uncurse_mode);
			//Su scadenza timer
			if (Time.time >= timer_start + timer_uncurse_mode)
			{
				this.ClearGhosts();
				tools = GameObject.FindGameObjectsWithTag("MagicTool");
				for (int i = 0; i < tools.Length; i++)
				{
					tools[i].Recycle();
				}
				return GameMode.Mortality;
			}
			return GameMode.UnCurse;
		case GameMode.Mortality:
//			if (Time.time >= timer_mortality_mode + timer_start)
//			{
//				return  GameMode.Winning;
//			}
            
			return GameMode.Mortality;
		case GameMode.Winning:
			if (Time.time >= timer_winning_mode + timer_start)
			{
                tools = GameObject.FindGameObjectsWithTag("MagicTool");
                for (int i = 0; i < tools.Length; i++)
                {
                    tools[i].Recycle();
                }
                    if (contRound == 1)
                        return GameMode.InstructionsEndRound;
                    else if (UIManager.getInstance().GetScore() > 0 && UIManager.getInstance().GetScore() < 1)
                    {
                        Debug.Log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!!!!!!!!!!!!!!!!!");
                        return GameMode.Spawning;
                    }
                        
                    
			}
			return GameMode.Winning;
            case GameMode.InstructionsEndRound:
                if (!instructionsEndRound.gameObject.activeSelf)
                    instructionsEndRound.gameObject.SetActive(true);
                return GameMode.InstructionsEndRound;
            case GameMode.End:
                return GameMode.End;
		default:
			Debug.LogWarning ("Unknown game mode  " + mode + " Restarted" );
			return GameMode.Spawning;
		}	
	}

	private void initMode(GameMode mode){
		switch (mode) {
            case GameMode.GameStart:
                break;
		case  GameMode.Spawning:
            UIManager.getInstance().UpdateTimer(0, timer_curse_mode);
            this.changeMusic(1);
            //SoundEffects.instance.PlaySound(SoundEffects.instance.playerSpawn);
            contRound++;
            timer_curse_mode += increaseCurse;
            timer_start = Time.time;
			player1.transform.position = new Vector3(-1000, -1000, 0);
			player2.transform.position = new Vector3(1000, 1000, 0);
			player1.GetComponent<PlayerMovement>().enabled = true;
			player2.GetComponent<PlayerMovement>().enabled = true;
			ClearGhosts();
			GameObject particleSystem = Instantiate(player1.particlesSpawning, spawningPoint1.position, Quaternion.identity) as GameObject;
			particleSystem.GetComponent<ParticleSystem>().startColor = Color.blue;
			particleSystem = Instantiate(player2.particlesSpawning, spawningPoint2.position, Quaternion.identity) as GameObject;
			particleSystem.GetComponent<ParticleSystem>().startColor = Color.red;
			break;
		case  GameMode.Curse:
            SoundEffects.instance.PlaySound(SoundEffects.instance.playerSpawn);
            tools = GameObject.FindGameObjectsWithTag("MagicTool");
            timer_start = Time.time;
			for (int i=0; i < bonus_spawn_first_stage; i++)
			{
				this.Spawn();
			}
			timer_last_spawn = Time.time;
			break;
            case GameMode.InstructionsUnCurse:
                break;
		case  GameMode.Evocation:
            this.changeMusic(2);
            //SoundEffects.instance.PlaySound(SoundEffects.instance.evocation);
            player1.GetComponent<PlayerMovement>().enabled = false;
            player2.GetComponent<PlayerMovement>().enabled = false;
            timer_start = Time.time;
			player1.Evocation();
			player2.Evocation();
			break;

		case  GameMode.UnCurse:
            player1.GetComponent<PlayerMovement>().enabled = true;
            player2.GetComponent<PlayerMovement>().enabled = true;
            this.SpawnGhosts();
			timer_start = Time.time;

			checkFastDead ();

			System.Array magicTools = System.Enum.GetValues(typeof(MagicToolEnum));
			foreach (MagicToolEnum n in magicTools)
			{
				this.ControlledSpawn(n);
			}
			tools = GameObject.FindGameObjectsWithTag("MagicTool");
			break;
		case GameMode.Mortality:
			timer_start = Time.time;
			player1.GetComponent<PlayerMovement>().enabled = false;
			player2.GetComponent<PlayerMovement>().enabled = false;
			//ThisPlayerWinRound(Random.value>=0.5?2:1);
			break;
		case GameMode.Winning:
            SoundEffects.instance.PlaySound(SoundEffects.instance.endGame);
			timer_start = Time.time;
			ClearGhosts();
			CheckEndGame();
			break;
            case GameMode.End:
                break;
		default:
			Debug.LogWarning ("Unknown game mode " + mode);
			break;
		}
	}

	//Check if one of the two playes (or both) colleted 0 magiTools. 
	private void checkFastDead(){
		if (player1.pickedUpSymbols.Count <= 0 && player2.pickedUpSymbols.Count > 0) {
			// the symbols are finished, the player wins
			ThisPlayerWinRound (player2.idPlayer, false);
			Debug.Log ("No symbol for player1, player2 win");

		} else
		if (player2.pickedUpSymbols.Count <= 0  && player1.pickedUpSymbols.Count > 0) {
			// the symbols are finished, the player wins
			ThisPlayerWinRound (player1.idPlayer, false);
			Debug.Log ("No symbol for player2, player1 win");

		}


	}



	private void CheckEndGame(){
        Debug.Log("BBBBBBBBBBBBBBBBBBBBBBB");
		if (UIManager.getInstance ().GetScore () <= 0) {
            //winningGameText.playerWinner = 2;
            //winningGameText.gameObject.SetActive(true);
			StartCoroutine(ShowText("Player 2 wins!"));
			StartCoroutine(ReloadScene());
		} else if (UIManager.getInstance ().GetScore () >= 1){
            //winningGameText.playerWinner = 1;
            //winningGameText.gameObject.SetActive(true);
            StartCoroutine(ShowText("Player 1 wins!")); 
            StartCoroutine(ReloadScene());
        }
	}

	private IEnumerator ReloadScene(){
		yield return new WaitForSeconds (3.2f);
		UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
	}
	
	void Update ()
    {
		if (changeMode) {
			initMode (Actual_State);
			changeMode = false;
		}
		GameMode newState = step (Actual_State);
		if (newState != Actual_State) {
			changeMode = true;
			Debug.Log ("New State "+newState+" actual "+Actual_State);
			Actual_State = newState;
		}

    }

    private void changeMusic(int n)
    {
        if (n == 1)
        {
            audioSource.clip = clip1;
        } 
        if (n == 2)
        {
            audioSource.clip = clip2;
        }
        audioSource.Play(); 
    }
    /*
    private void makeSound(int n)
    {
        if (n == 1)
            audioSounds.clip = endGameClip;
        if (n == 2)
            audioSounds.clip = evocationClip;
        if (n == 3)
            audioSounds.clip = playerSpawnClip;



        audioSource.Play();
    }
    */
	private void SpawnPlayers(){
		this.SpawnPlayer(player1, spawningPoint1);
		this.SpawnPlayer(player2, spawningPoint2);
		player1.Spawning();
		player2.Spawning();
		//Actual_State = GameMode.Curse;
	}

	public void SpawnGhosts(){
		float scoreP2 = UIManager.getInstance().GetScore () * 10;
		float scoreP1 = 10 - scoreP2;Debug.Log (scoreP1);

		ghost1 = Instantiate(ghost, new Vector3(0, 0, 0), Quaternion.identity) as Ghost;
		ghost1.TargetPlayer = player2;
		ghost1.transform.localScale = new Vector3 (0.65f, 0.65f, 1f) + new Vector3 (0.2f*scoreP1, 0.2f*scoreP1, 0) ;
		ghost1.GetComponent<Ghost> ().spriteRenderer.color = new Color(0,0.2f,0.95f,0.6f);
		ghost2 = Instantiate(ghost, new Vector3(0, 0, 0), Quaternion.identity) as Ghost;
		ghost2.TargetPlayer = player1;
		ghost2.transform.localScale = new Vector3 (0.65f, 0.65f, 1f) + new Vector3 (0.2f*scoreP2, 0.2f*scoreP2, 0) ;
		ghost2.GetComponent<Ghost> ().spriteRenderer.color = new Color(0.95f,0.2f,0.1f,0.6f);
	}

    public void ClearGhosts()
    {
        GameObject[] ghosts = GameObject.FindGameObjectsWithTag("Ghost");
        for(int i=0; i<ghosts.Length; i++)
        {
            Destroy(ghosts[i]);
        }
    }

    public void Spawn ()
    {
        float random_width = (Random.value * arena_width) - (arena_width / 2);
        float random_height = (Random.value * arena_height) - (arena_height / 2);

        tool1 = Tool.Spawn(new Vector3(random_width, random_height, 0), Quaternion.identity);
        //tool1 = Instantiate(Tool, new Vector3(random_width, random_height, 0), Quaternion.identity) as MagicTool;
        // random type
		System.Array magicTools = System.Enum.GetValues(typeof(MagicToolEnum));
		int random = Mathf.FloorToInt(Random.value * magicTools.Length);
		MagicToolEnum randType = (MagicToolEnum)magicTools.GetValue(random);
		tool1.SetType(randType);
    }

    public void ControlledSpawn(MagicToolEnum t)
    {
        float random_width = (Random.value * arena_width) - (arena_width / 2);
        float random_height = (Random.value * arena_height) - (arena_height / 2);
        tool1 = Tool.Spawn(new Vector3(random_width, random_height, 0), Quaternion.identity);
        //tool1 = Instantiate(Tool, new Vector3(random_width, random_height, 0), Quaternion.identity) as MagicTool;
        // set type
        tool1.SetType(t);
    }

    public void Repositioning (MagicTool t)
    {
        float random_width = (Random.value * arena_width) - (arena_width / 2);
        float random_height = (Random.value * arena_height) - (arena_height / 2);
        t.transform.position = new Vector3(random_width, random_height, 0);
    }

    public void SpawnPlayer (PlayerManager p, Transform t)
    {
        p.transform.position = t.position;
    }

    public void ThisPlayerWinRound(int i, bool ghostWin)
    {
		if (ghostWin) {
			Debug.Log ("Player " + i + " wins round " + contRound);
			if (i == 1) {
				UIManager.getInstance ().UpdateScoreBar (contRound * -0.1f);
			} else {
				UIManager.getInstance ().UpdateScoreBar (contRound * 0.1f);
			}
		}

		// distruggi il ghost del giocatore vincente, velocizza l'altro
		if (i == 1) {
			Destroy (ghost2);
			ghost1.GetComponent<Ghost>().MovedSpeed *= 5; 
		} else {
			Destroy (ghost1);
			ghost2.GetComponent<Ghost>().MovedSpeed *= 5; 
		}
		// reset
		if (!ghostWin) {
            Actual_State = GameMode.Mortality;
            initMode(Actual_State);
        } else {
			if(i==1){
				Instantiate(player2.particlesDeath, player2.transform.position, Quaternion.identity);
				player2.transform.position = new Vector3(1000,1000,0);
			}else{
                Instantiate(player1.particlesDeath, player1.transform.position, Quaternion.identity);
                player1.transform.position = new Vector3(1000,1000,0);
			}

            Actual_State = GameMode.Winning;
            initMode(Actual_State);
            StartCoroutine (ShowText("Player " + (i==1?2:1) + " has been slayed!"));
		}
		changeMode = true;
		tools = GameObject.FindGameObjectsWithTag("MagicTool");
		for (int j = 0; j < tools.Length; j++)
		{
			tools[i].Recycle();
		}
    }

    public static GameFlow getInstance ()
    {
        return instance;
    }

	public IEnumerator ShowText(string text){
		textScreen.text = text;
		textScreen.gameObject.SetActive(true);
		yield return new WaitForSeconds (2);
		textScreen.gameObject.SetActive(false);
	}
    
}
