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

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    [SerializeField] private GameObject powerStation;
    [SerializeField] private GameObject influence;
    [SerializeField] private Transform housesParent;
    [SerializeField] private Transform connectorsParent;
    [SerializeField] private LayerMask housesLayer;
    [SerializeField] private float newHoodTimer;
    [SerializeField] private float timeToGetAngry;
    [SerializeField] private float newStationCounter;

    [SerializeField] private Text availableStationsText;
    [SerializeField] private Text timerText;

    [SerializeField] private Text pointsText;
    [SerializeField] private Text strikesText;

    [SerializeField] private GameObject openingPaenl;
    [SerializeField] private GameObject ingamePanel;
    [SerializeField] private GameObject gameOverPanel;


    [Header("Testing")]
    [SerializeField] private List<Vector3Int> hoodsPoses;

    public Transform HousesParent { get { return housesParent; } }
    public Transform ConnectorsParent { get { return connectorsParent; } }
    public LayerMask HousesLayerMask { get { return housesLayer; } }
    public int InfluencesCounter { get { return influencesCounter; } }
    public float TimeToGetAngry { get { return timeToGetAngry; } }
    public int AvailableStation { get { return availableStation; } }
    public bool GameIsOver { get; private set; }

    //private List<HoodManager> hoods;
    private List<InfluenceRadius> influences;

    public List<Vector3Int> ForbiddenPositions { get { return forbiddenPositions; } }
    private List<Vector3Int> forbiddenPositions;
    private int influencesCounter;
    private float stationCountdown;
    private HoodManager hoodManager;
    private int hoodToCreate;

    private int availableStation;
    private int points;
    private int maxStrikes = 15;
    private int strikes;

    private int highscore;
    private bool musicIsOn = true;

    void Awake()
    {
        if(Instance != null)
        {
            Destroy(this.gameObject);
            return;
        }

        Instance = this;
    }

    void Start()
    {
        NewGame();   
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }
    }

    public void NewGame()
    {
        if(housesParent.childCount > 0)
        {
            foreach (Transform child in housesParent)
            {
                Destroy(child.gameObject);
            }
        }

        if (connectorsParent.childCount > 0)
        {
            foreach (Transform child in connectorsParent)
            {
                Destroy(child.gameObject);
            }
        }

        openingPaenl.SetActive(true);
        ingamePanel.SetActive(false);
        gameOverPanel.SetActive(false);

        if(hoodManager == null)
            hoodManager = GetComponent<HoodManager>();

        hoodManager.NewGame();
        hoodToCreate = 0;
        points = 0;
        pointsText.text = points.ToString();
        strikes = 0;
        strikesText.text = strikes.ToString();

        availableStation = 1;

        highscore = PlayerPrefs.HasKey("Highscore") ? PlayerPrefs.GetInt("Highscore") : 0;
        GameIsOver = false;
    }

    public void StartGame()
    {
        openingPaenl.SetActive(false);
        ingamePanel.SetActive(true);
        gameOverPanel.SetActive(false);

        GameIsOver = false;

        UpdateStationCounter();
        Instantiate(powerStation, Vector3Int.zero, Quaternion.identity);
        forbiddenPositions = new List<Vector3Int>();
        influences = new List<InfluenceRadius>();
        influencesCounter = 0;
        PopulateForbidden();

        StartCoroutine(RefillStationCount());
        StartCoroutine(CreateHoods());
    }

    IEnumerator CreateHoods()
    {
        while (true)
        {
            if (hoodToCreate >= hoodsPoses.Count)
                break;

            while (hoodManager.Houses.Contains(hoodsPoses[hoodToCreate]))
            {
                hoodToCreate++;
            }

            hoodManager.StartNewHood(hoodsPoses[hoodToCreate]);
            hoodToCreate++;
            yield return new WaitForSeconds(newHoodTimer);
        }
    }

    private void PopulateForbidden()
    {
        for (int i = -1; i < 2; i++)
        {
            for (int j = -2; j < 3; j++)
            {
                forbiddenPositions.Add(new Vector3Int(j, i, 0));
            }
        }

        for (int j = -1; j < 2; j++)
        {
            forbiddenPositions.Add(new Vector3Int(j, -2, 0));
            forbiddenPositions.Add(new Vector3Int(j, 2, 0));
        }
    }

    public void InfluenceAdded(InfluenceRadius ir)
    {
        influences.Add(ir);
        influencesCounter++;
        availableStation--;
        UpdateStationCounter();
    }

    public bool InInfluenceArea(Vector3Int point)
    {
        for (int i = 0; i < influences.Count; i++)
        {
            if (influences[i].GetInfluencedLocations().Contains(point))
                return true;
         }

        return false;
    }

    private void UpdateStationCounter()
    {
        availableStationsText.text = availableStation.ToString();
    }

    public void ChangeMusic()
    {
        AudioSource audio = GetComponent<AudioSource>();
        if(musicIsOn)
        {
            musicIsOn = false;
            audio.Stop();
        }
        else
        {
            musicIsOn = true;
            audio.Play();
        }
    }

    IEnumerator RefillStationCount()
    {
        while(true)
        {

            if (stationCountdown < 0)
            {
                availableStation++;
                UpdateStationCounter();
                stationCountdown = newStationCounter;
            }

            timerText.text = stationCountdown.ToString();

            yield return new WaitForSeconds(1f);
            stationCountdown--;
        }
    }

    public void HousePositioned()
    {
        points++;
        pointsText.text = points.ToString("N0");
    }

    public void HouseGotAngry()
    {
        strikes++;
        strikesText.text = strikes.ToString();

        if(strikes >= maxStrikes)
        {
            Debug.Log("Game Over");
            GameOver();
        }
    }

    public void GameOver()
    {
        bool isNewHigh = false;
        GameIsOver = true;

        if(points > highscore)
        {
            isNewHigh = true;
            highscore = points;
            PlayerPrefs.SetInt("Highscore", highscore);
        }

        gameOverPanel.GetComponent<GameOverPanel>().Set(points, highscore, isNewHigh);

        openingPaenl.SetActive(false);
        ingamePanel.SetActive(false);
        gameOverPanel.SetActive(true);
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        for (int i = -15; i < 16; i++)
        {
            for (int j = -15; j < 16; j++)
            {
                Gizmos.DrawSphere(new Vector3Int(i, j, 0), 0.1f);

            }

        }

        Gizmos.color = Color.cyan;
        for (int i = -10; i < 11; i++)
        {
            for (int j = -10; j < 11; j++)
            {
                Gizmos.DrawSphere(new Vector3Int(i, j, 0), 0.1f);

            }

        }

        Gizmos.color = Color.yellow;
        for (int i = -5; i < 6; i++)
        {
            for (int j = -5; j < 6; j++)
            {
                Gizmos.DrawSphere(new Vector3Int(i, j, 0), 0.1f);

            }

        }

        Gizmos.color = Color.red;
        if (forbiddenPositions != null && forbiddenPositions.Count > 0)
        {
            for (int i = 0; i < forbiddenPositions.Count; i++)
            {
                Gizmos.DrawSphere(ForbiddenPositions[i], 0.1f);

            }
        }

        
    }
}
