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


public class GameManager : MonoBehaviour {

    private static GameManager _instance;

    public static GameManager Instance
    {
        get
        {
            return _instance;
        }
    }

    private GameObject[] _players;
    [SerializeField]
    private List<Sprite> _shipSprites;
    [SerializeField]
    private List<Color> _colors;
    [SerializeField]
    private List<string> _names;
    public GameObject Player;
    public Animator _cameraAnimator;
    public List<LimitsController> _limitsControllers;

    private int _numPlayers;

    private bool _gameInProgress = true;


    private const float WORLD_CENTER = 7f;
    
    // Use this for initialization
    void Awake() {

        if(_instance == null)
        {
            _instance = this;
        }
        else
        {
            Destroy(gameObject);
            return;
        }

        _numPlayers = GameSettingsManager.Instance.GetNumberOfPlayers();
        _players = new GameObject[_numPlayers];

        _cameraAnimator = GameObject.FindGameObjectWithTag("Camera").GetComponent<Animator>() ;

        //Randomize Color
        for (int i = 0; i < _colors.Count; i++)
        {
            int tmpIndex = Random.Range(0, _colors.Count - 1);
            Color tmpColor = _colors[tmpIndex];
            _colors[tmpIndex] = _colors[i];
            _colors[i] = tmpColor;
        }
        //Randomize Sprite
        for (int i = 0; i < _shipSprites.Count; i++)
        {
            int tmpIndex = Random.Range(0, _shipSprites.Count - 1);
            Sprite tmpSprite = _shipSprites[tmpIndex];
            _shipSprites[tmpIndex] = _shipSprites[i];
            _shipSprites[i] = tmpSprite;

        }
        //Randomize Name
        for (int i = 0; i < _names.Count; i++)
        {
            int tmpIndex = Random.Range(0, _names.Count - 1);
            string tmpSprite = _names[tmpIndex];
            _names[tmpIndex] = _names[i];
            _names[i] = tmpSprite;

        }

        //Initialice players
        for (int i = 0; i < _numPlayers; i++)
        {
            _players[i] = (GameObject)Instantiate(Player, null, true) as GameObject;
            _players[i].GetComponent<PlayerController>()._playerId = i;
            _players[i].GetComponent<PlayerController>()._playerColor = _colors[i];
            _players[i].GetComponent<PlayerController>().Name = _names[i];
            _players[i].GetComponent<PlayerController>()._cameraAnimator = _cameraAnimator;
            _players[i].GetComponent<PlayerController>().PlayerImage.GetComponent<SpriteRenderer>().sprite = _shipSprites[i];
        }

        PositionPlayers();

        AudioManager.Instance.StartIngameMusic();
    }

    public List<PlayerController> GetPlayerControllerList()
    {
        List<PlayerController> playerList = new List<PlayerController>();

        for (int i = 0; i < _players.Length; i++)
        {
            playerList.Add(_players[i].GetComponent<PlayerController>());
        }

        return playerList;
    }

    private void PositionPlayers()
    {
        float offset = WORLD_CENTER * 2 / (_numPlayers - 1);
        float currentXPosition = -WORLD_CENTER;
        for (int i = 0; i < _numPlayers; i++)
        {
            _players[i].transform.position = new Vector3(currentXPosition, 0, 0);
            _players[i].GetComponent<PlayerController>().ResetPlayer();
            currentXPosition += offset;
        }
    }

    public void CheckWinCondition()
    {
        StopCoroutine("CheckWinConditionLogic");
        StartCoroutine("CheckWinConditionLogic");
    }

    public IEnumerator CheckWinConditionLogic()
    {
        yield return new WaitForSeconds(1f);
        if(_gameInProgress)
        {
            List<PlayerController> playerList = GetPlayerControllerList();
            PlayerController alive = null;
            int numberOfAlive = 0;
            for (int i = 0; i < playerList.Count; i++) {
                if(!playerList[i].Dead)
                {
                    alive = playerList[i];
                    numberOfAlive++;
                }
            }

            if(numberOfAlive < 2)
            {
                if(alive == null)
                {
                    //draw
                    _gameInProgress = false;
                    UIManager.Instance.ShowDrawScreen();

                }
                else
                {
                    _gameInProgress = false;
                    alive.IncreaseScore();
                    UIManager.Instance.ShowWinScreen(alive);
                }
            }
        }
    }

    public void ResetPlayers()
    {
        _gameInProgress = true;
        PositionPlayers();
        DeleteBombs();
        AudioManager.Instance.StartIngameMusic();
    }

	// Update is called once per frame
	void Update () {
		
	}

    private void DeleteBombs()
    {
        GameObject[] bombs = GameObject.FindGameObjectsWithTag("Bomb");

        for (int i = 0; i < bombs.Length; i++)
        {
            Destroy(bombs[i]);
        }
    }

    public void StopWalls()
    {
        foreach (LimitsController limitController in _limitsControllers)
        {
            limitController.StopMovement();
        }
    }

    public void ResetWalls()
    {
        foreach (LimitsController limitController in _limitsControllers)
        {
            limitController.ResetLimit();
        }
    }

    public bool ReachedRoundScore()
    {
        List<PlayerController> playerList = GetPlayerControllerList();
        foreach (PlayerController player in playerList)
        {
            if(player.GetScore() == GameSettingsManager.Instance.GetNumberOfRounds())
            {
                return true;
            }
        }

        return false;
    }

    public PlayerController GetRoundWinnerPlayer()
    {
        List<PlayerController> playerList = GetPlayerControllerList();
        PlayerController winningPlayer = null;
        foreach (PlayerController player in playerList)
        {
            if(player.GetScore() == GameSettingsManager.Instance.GetNumberOfRounds())
            {
                winningPlayer = player;
            }
        }

        return winningPlayer;
    }
}

