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

public enum EGameState
{
    attract = 0,
    main_menu,
    gameplay,
    paused,
    gameover,
    enter_name,
    leaderboards,
    options,
}

public class GameManager : MonoBehaviour
{
    private static GameManager instance;
    public static GameManager GetGame()
    {
        if (instance == null)
        {
            instance = GameObject.Find("GameManager").GetComponent<GameManager>();
        }

        return instance;
    }

    private List<GameObject> spawnedObjects;

    private EGameState gameState;
    [Header("Debug Flags")] 
    public bool SkipMenusJustPlay;

    [Header("World Data")]
    private LDTerrainManager theTerrainManager;

    public MapGrid theWorld
    {
        get { return theTerrainManager.theMap; }
    }
    [Header("Gameplay")] 
    public LDPlayer thePlayer;

    private int iScore;
    private float fScoreMultiplier = 1.0f;
    public float MinRangeToAlertPlayerAboutBaseAttack;

    [Header("Colors and Fun!")] 
    public Color color_Red;
    public Color color_Orange;
    public Color color_Gold;
    public GameObject Prefab_SummoningPoof;
    public GameObject Prefab_Multifoom;

    [Header("UI Info")] 
    public GameObject HUDFolder;
    [HideInInspector]
    public UI_Leaderboards uiLeaderboards;
    private string strPlayerNameForHighScores;
    [HideInInspector]
    public UI_EnterName uiEnterName;
    [HideInInspector]
    public UI_GameOver uiGameOver;
    [HideInInspector]
    public UI_Gameplay uiGameplay;
    [HideInInspector]
    public UI_Attract uiAttract;

    [HideInInspector]
    public LDAIManager theAIManager;
    [HideInInspector]
    public LDCameraManager theCamera;
    [HideInInspector]
    public LDWorldSpawnManager theWorldSpawnManager;
    [HideInInspector]
    public LDGrowthManager theGrowthManager;

    private int iVersion = 1;

    //1: first time I added a version number

	// Use this for initialization
	void Awake ()
	{
        for (int t = 0; t < HUDFolder.transform.childCount; t++)
        {
            Transform tf = HUDFolder.transform.GetChild(t);
            tf.gameObject.SetActive(true);
        }

	    uiLeaderboards = GameObject.Find("UI_Leaderboards").GetComponent<UI_Leaderboards>();
        uiEnterName = GameObject.Find("UI_EnterName").GetComponent<UI_EnterName>();
        uiGameOver = GameObject.Find("UI_GameOver").GetComponent<UI_GameOver>();
        uiGameplay = GameObject.Find("UI_Gameplay").GetComponent<UI_Gameplay>();
        uiAttract = GameObject.Find("UI_Attract").GetComponent<UI_Attract>();

        thePlayer = GameObject.Find("Player").GetComponent<LDPlayer>();
	    theCamera = Camera.main.GetComponent<LDCameraManager>();

	    theTerrainManager = GameObject.Find("TerrainManager").GetComponent<LDTerrainManager>();
	    theAIManager = GameObject.Find("AIManager").GetComponent<LDAIManager>();

	    theWorldSpawnManager = GameObject.Find("WorldSpawnManager").GetComponent<LDWorldSpawnManager>();

	    theGrowthManager = GameObject.Find("GrowthManager").GetComponent<LDGrowthManager>();

        spawnedObjects = new List<GameObject>();
	}

    void Start()
    {
        if (PlayerPrefs.GetInt("version") < iVersion)
        {
            PlayerPrefs.DeleteAll();
            PlayerPrefs.SetInt("version", iVersion);
        }

        TM_AudioManager.InitSources();

        if (SkipMenusJustPlay)
        {
            StartNewGame();
        }
        else
        {
            SetGameState(EGameState.attract);
        }
    }
	// Update is called once per frame
	void Update () 
    {
        TM_AudioManager.Update();

        if (spawnedObjects != null)
        {
            spawnedObjects.RemoveAll( a => a == null );
        }

        if (Input.GetKeyDown(KeyCode.Alpha9))
        {
            thePlayer.TakeDamage(99999,thePlayer);
        }
	}

    //do whatever we gotsta do here
    public void StartNewGame()
    {
        spawnedObjects.RemoveAll(a => a == null);
        spawnedObjects.ForEach(a => Destroy(a));

        iScore = 0;
        theAIManager.PrepareNewGame();
        thePlayer.PrepareForNewGame();
        theTerrainManager.PrepareNewGame();

        SetGameState(EGameState.gameplay);

        uiGameplay.PrepareForNewGame();

        theWorldSpawnManager.PrepareForNewGame();
        theWorldSpawnManager.PlaceStartingAsteroids(theTerrainManager.vStartLocation);
        theGrowthManager.OnNewGame();
    }

    public int GetScore()
    {
        return iScore;
    }

    public void AddScore(int iPoints)
    {
        iPoints = (int) ((float) iPoints * fScoreMultiplier);
        iScore += iPoints;
    }

    public void SetGameState(EGameState newState)
    {
        gameState = newState;
        switch (newState)
        {
            case EGameState.attract:
                uiAttract.TurnOn();
                break;
            case EGameState.gameplay:
                uiAttract.TurnOff();
                uiGameplay.TurnOn();
                break;
            case EGameState.gameover:
                uiGameplay.TurnOff();
                uiGameOver.TurnOn();
                break;
        }
    }

    public EGameState GetGameState() { return gameState; }

    public string GetSizeOfPlanetString()
    {
        int iGrowthLevel = theGrowthManager.iGrowthScore;
        if (iGrowthLevel < 10)
        {
            fScoreMultiplier = 1.0f;
            return "V. V. Smol";
        }
        else if (iGrowthLevel < 40)
        {
            fScoreMultiplier = 1.0f;
            return "V Small";
        }
        else if (iGrowthLevel < 80)
        {
            fScoreMultiplier = 1.0f;
            return "P Small";
        }
        else if (iGrowthLevel < 250)
        {
            fScoreMultiplier = 1.1f;
            return "Cramped";
        }
        else if (iGrowthLevel < 500)
        {
            fScoreMultiplier = 1.15f;
            return "Comfy";
        }
        else if (iGrowthLevel < 750)
        {
            fScoreMultiplier = 1.2f;
            return "Spacious";
        }
        else if (iGrowthLevel < 1200)
        {
            fScoreMultiplier = 1.25f;
            return "Regal";
        }
        else if (iGrowthLevel < 2400)
        {
            fScoreMultiplier = 1.5f;
            return "Colossal";
        }
        else if (iGrowthLevel < 3600)
        {
            fScoreMultiplier = 2.0f;
            return "Massive";
        }
        fScoreMultiplier = 3.0f;
        return "Your Mom";
    }

    public string GetHighScoreName()
    {
        if (string.IsNullOrEmpty(strPlayerNameForHighScores))
        {
            strPlayerNameForHighScores = PlayerPrefs.GetString("highscorename");
            if (string.IsNullOrEmpty(strPlayerNameForHighScores))
            {
                return null;
            }
        }

        PlayerPrefs.SetString("highscorename", strPlayerNameForHighScores);
        return strPlayerNameForHighScores;
    }

    public void SetHighScoreName(string newName)
    {
        strPlayerNameForHighScores = newName;
        PlayerPrefs.SetString("highscorename", strPlayerNameForHighScores);
    }

    public void EndGameOverState()
    {
        if (SkipMenusJustPlay)
        {
            return;
        }

        uiGameOver.TurnOff();

        //if we have a name, submit it and yeah good job
        if (!string.IsNullOrEmpty(GetHighScoreName()))
        {
            gameState = EGameState.leaderboards;
            uiLeaderboards.TurnOn();
            uiLeaderboards.SubmitHighScore(strPlayerNameForHighScores, iScore);
        }
        //otherwise, go get name
        else
        {
            //generate a fake name
            SetHighScoreName("No Name Jabroni");

            gameState = EGameState.enter_name;
            uiEnterName.TurnOn();
        }
    }

    public void UpdateWorldFromTileChange()
    {
        theTerrainManager.UpdateUVs();
    }

    public void OnAddNewLand()
    {
        //score goes up

        theGrowthManager.iGrowthScore++;

        AddScore(10);
    }

    public Vector2 GetGameWorldPositionFromTransformPosition(Vector3 vUnityPosition)
    {
        Vector2 cameraPos = theCamera.GetWorldPosition();
        Vector2 vFromCamToMe = (Vector2) vUnityPosition - (Vector2)theCamera.transform.position;
        cameraPos += vFromCamToMe;
        return cameraPos;
        
    }

    public Vector3 GetScreenspaceVectorFromGamePosition(Vector2 vGamePos)
    {
        Vector3 vDrawPos = theCamera.transform.position;
        vDrawPos += (Vector3)(vGamePos - theCamera.GetWorldPosition());
        vDrawPos.z = -1;

        return vDrawPos;
    }

    public GameObject PlaySummoningPoof(Vector2 vGamePos)
    {
        return PlayParticleEffect(vGamePos, Prefab_SummoningPoof);
    }

    public void PlayMultifoom(Vector2 vGamePos)
    {
        SpawnActorPrefab(vGamePos, Prefab_Multifoom);
        theCamera.fScreenshake += 0.5f;
    }

    public GameObject PlayParticleEffect(Vector2 vGamePos, GameObject prefab)
    {
        GameObject go = Instantiate(prefab);
        Vector3 vNewPos = GetScreenspaceVectorFromGamePosition(vGamePos);
        vNewPos.z = theCamera.gameObject.transform.position.z + 2;
        go.transform.position = vNewPos;
        Destroy(go, 3.0f);
        spawnedObjects.Add(go);

        //If the particle has a gameactor, keep it updated
        LDGameActor ga = go.GetComponent<LDGameActor>();
        if (ga != null)
        {
            ga.vWorldPos = vGamePos;
        }

        return go;
    }

    public LDGameActor SpawnActorPrefab(Vector2 vGamePos, GameObject prefab)
    {
        GameObject go = Instantiate(prefab);
        Vector3 vNewPos = GetScreenspaceVectorFromGamePosition(vGamePos);
        vNewPos.z = 0;
        go.transform.position = vNewPos;
        spawnedObjects.Add(go);

        LDGameActor ga = go.GetComponent<LDGameActor>();
        if (ga == null)
        {
            Debug.LogError("lol what");
            return null;
        }

        ga.vWorldPos = vGamePos;
        return ga;
    }

    public void MaybeAlartPlayerAboutBase(Vector2 vPingPosition)
    {
        float fDistSQ = (vPingPosition - (Vector2) thePlayer.vWorldPos).sqrMagnitude;
        if (fDistSQ >= MinRangeToAlertPlayerAboutBaseAttack * MinRangeToAlertPlayerAboutBaseAttack)
        {
            uiGameplay.RemindPlayerAboutBase();
        }
    }
}
