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

public class LevelMaker : MonoBehaviour
{
    //from 0 to here, no enemies spawn or are placed.
    public int MileMarkerSafetyRange = 40;

    public GameObject prefab_playermans;

    public GameObject prefab_solidFloor;
    public GameObject prefab_dropFloor;
    public GameObject prefab_crate32;
    public GameObject prefab_crate16;
    public GameObject prefab_changeUp;

    public GameObject prefab_basicDoor;
    public GameObject prefab_ladyDoor;
    public GameObject prefab_exitDoor;

    public GameObject prefab_milady;
    public GameObject prefab_baseEnemy;
    public GameObject prefab_rangerEnemy;
    public GameObject prefab_paladinEnemy;
    public GameObject prefab_harrierEnemy;
    public GameObject prefab_bardEnemy;
    public GameObject prefab_wizardEnemy;
    public GameObject prefab_sharpshooterEnemy;
    public GameObject prefab_dragonEnemy;

    private int iMileMarker;

    public int iLevelDifficulty;

	// Use this for initialization
    private void Start()
    {
    }

    public GameObject MakeLevel( int _iLevelDifficulty, GameObject playerObject )
    {
        iLevelDifficulty = _iLevelDifficulty;

        if (playerObject == null)
        {
            playerObject = Instantiate(prefab_playermans);
            playerObject.name = "PlayerMans";
            DontDestroyOnLoad(playerObject);

        }

        playerObject.transform.position = new Vector3(0,0,0);
        playerObject.SetActive(true);

        float fFloorHeight = -4.0f;
	    float fSecondFloorHeight = fFloorHeight + 5.0f;

	    iMileMarker = 0;
        //If we are within one tile of an elevation change UP,
        //any second story tiles need to be dropfloors so we don't
        //get stuck jumping

	    bool bRaiseFloorNextTime = false;

	    bool bLastBottomFloorWasSmallCrate = false;
        bool bLastTopFloorWasSmallCrate = false;

	    GameObject enemyPrefab = null;

        float fBuildingDatWall = fFloorHeight + 0.75f;

        Debug.Log("Making new floor!");


        for (int y = 0; y < 20; y++)
        {
            PlaceFloorPrefabAtLocation(new Vector3(-2, fBuildingDatWall, 0), prefab_changeUp, false, ref bLastBottomFloorWasSmallCrate);
            fBuildingDatWall += 2;
        }

	    for(int x = 0; x < 100 + 40 * iLevelDifficulty; x+= 2)
	    {
	        iMileMarker = x;
	        enemyPrefab = null;
            //maybe we should be a rangermans?
	        if (bLastBottomFloorWasSmallCrate && Random.value < 0.5f)
	            enemyPrefab = GetRangerTypeBasedOnMileMarker();
	        else if( Random.value < 0.2f)
	        {
	            enemyPrefab = GetRandomEnemy();
	        }

	        bool bForceSecondFloorDropFloor = false;
            //raise floor sometimes
	        if (bRaiseFloorNextTime)
	        {
                PlaceFloorPrefabAtLocation(new Vector3(x, fFloorHeight, 0), prefab_solidFloor, false, ref bLastBottomFloorWasSmallCrate);
                PlaceFloorPrefabAtLocation(new Vector3(x, fFloorHeight + 1.25f, 0), prefab_changeUp, false, ref bLastBottomFloorWasSmallCrate);
	            fFloorHeight += 2f;

	            bForceSecondFloorDropFloor = true;
	            bRaiseFloorNextTime = false;

	        }
            //lower floor sometimes?
            else if (Random.value <= 0.08f && iMileMarker > MileMarkerSafetyRange)
            {
                PlaceFloorPrefabAtLocation(new Vector3(x, fFloorHeight - 0.75f, 0), prefab_changeUp, false, ref bLastBottomFloorWasSmallCrate);
                fFloorHeight -= 2f;
                PlaceFloorPrefabAtLocation(new Vector3(x, fFloorHeight, 0), prefab_solidFloor, false, ref bLastBottomFloorWasSmallCrate);
            }
            else
                PlaceFloorPrefabAtLocation(new Vector3(x, fFloorHeight, 0), prefab_solidFloor, true, ref bLastBottomFloorWasSmallCrate);


            if (enemyPrefab != null)
                PlaceEnemyPrefabAtLocation(new Vector3(x, fFloorHeight, 0), enemyPrefab);


            //maybe raise floor next time?
            if (Random.value <= 0.1f && iMileMarker > MileMarkerSafetyRange)
	        {
	            bRaiseFloorNextTime = true;
	            bForceSecondFloorDropFloor = true;
	        }
            
            if( iMileMarker < 24 || iLevelDifficulty == 0 )
                continue;

            //second floor
	        enemyPrefab = null;
            //maybe we should be a rangermans?
	        if (bLastTopFloorWasSmallCrate && Random.value < 0.2f)
	            enemyPrefab = GetRangerTypeBasedOnMileMarker();
            else if (Random.value < 0.05f)
            {
                enemyPrefab = GetRandomEnemy();
            }

            Vector3 newTileLocation = new Vector3(x, fSecondFloorHeight, 0);
	        GameObject floorObj = prefab_solidFloor;
	        if (Random.value < 0.2f || bForceSecondFloorDropFloor)
	            floorObj = prefab_dropFloor;

	        bool bMaybeCrates = floorObj != prefab_dropFloor;

            PlaceFloorPrefabAtLocation(newTileLocation, floorObj, bMaybeCrates, ref bLastTopFloorWasSmallCrate);

	        if (enemyPrefab != null)
	            PlaceEnemyPrefabAtLocation(newTileLocation, enemyPrefab);


            //if we're not raising the floor next time, and we forced ourselves to be a drop floor this time, raise up.
	        if (!bRaiseFloorNextTime && bForceSecondFloorDropFloor)
	            fSecondFloorHeight = fFloorHeight + 5.0f;

	        bForceSecondFloorDropFloor = false;
	    }

        fBuildingDatWall = fFloorHeight + 0.75f;

        //final floor tile with exit door
        PlaceFloorPrefabAtLocation(new Vector3(iMileMarker + 2, fFloorHeight, 0), prefab_solidFloor, false, ref bLastBottomFloorWasSmallCrate);
        GameObject newDoor = Instantiate(prefab_exitDoor);
        Vector3 vDoorPos = new Vector3(iMileMarker + 2, fFloorHeight, 0);
        vDoorPos.y += 0.25f + 1.5f;
        newDoor.transform.position = vDoorPos;
        newDoor.transform.parent = transform;

        for (int t = 5; t < iLevelDifficulty; t += 4)
        {
            PlaceEnemyPrefabAtLocation(new Vector3(iMileMarker - Random.Range(4,11), fFloorHeight + Random.Range(3,7), 0), prefab_dragonEnemy);
        }

        for (int y = 0; y < 20; y++)
        {
            PlaceFloorPrefabAtLocation(new Vector3(iMileMarker +4, fBuildingDatWall, 0), prefab_changeUp, false, ref bLastBottomFloorWasSmallCrate);
            fBuildingDatWall += 2;
        }

        GUIManager myGUI = GameObject.Find("GUIManager").GetComponent<GUIManager>();
        if (myGUI != null)
        {
            myGUI.iFloorNumber = iLevelDifficulty + 1;
            myGUI.fNewFloorTimer = 7.0f;
        }

        return playerObject;
	}

    GameObject GetRangerTypeBasedOnMileMarker()
    {
        GameObject baseRanger = iLevelDifficulty > 4 ? prefab_sharpshooterEnemy : prefab_rangerEnemy;

        if (iMileMarker < 100 || iLevelDifficulty < 3)
            return baseRanger;

        float fHarrierChance = (float) (iMileMarker - 100)/100.0f;

        if (fHarrierChance > 0.5f)
            fHarrierChance = 0.5f;

        if( Random.value < fHarrierChance)
            return prefab_harrierEnemy;

        return baseRanger;
    }

    GameObject GetRandomEnemy()
    {
        float fRando = Random.value;
        if( fRando < 0.12f && iMileMarker > 30 )
            return prefab_milady;
        if (iLevelDifficulty == 0)
            return prefab_baseEnemy;
        if( fRando < 0.27f && iLevelDifficulty > 1)
            return prefab_paladinEnemy;
        else if (fRando < 0.47f)
            return GetRangerTypeBasedOnMileMarker();

        //random baseEnemy
        if( iMileMarker < 100 || iLevelDifficulty <= 3 )
            return prefab_baseEnemy;

        //roll again
        fRando = Random.value;
        float fBonusToughChance = iLevelDifficulty < 4 ? 0.0f : 0.2f;
        if (fRando < 0.2f +  fBonusToughChance )
            return prefab_bardEnemy;
        if (fRando < 0.4f + fBonusToughChance + fBonusToughChance)
            return prefab_wizardEnemy;

        return prefab_baseEnemy;
    }

    void PlaceFloorPrefabAtLocation(Vector3 vLoc, GameObject prefabObject, bool bMaybeCrates, ref bool bPlacedSmallCrate )
    {
        bPlacedSmallCrate = false;
        GameObject newGo = GameObject.Instantiate(prefabObject);
        newGo.transform.position = vLoc;
        newGo.layer = prefabObject.layer;

        newGo.transform.parent = transform;

        float fHalfFloorHeight = 0.25f;

        if (bMaybeCrates && Random.value < 0.2f)
        {
            GameObject crateFab = Random.value < 0.2f ? prefab_crate32 : prefab_crate16;

            bPlacedSmallCrate = crateFab == prefab_crate16;
            newGo = GameObject.Instantiate(crateFab);

            //raise the box by...
            float yDelta = fHalfFloorHeight + newGo.GetComponent<BoxCollider2D>().size.y * 0.5f;
            Vector3 vCratePos = vLoc;
            vCratePos.y += yDelta;

            newGo.transform.position = vCratePos;

        }
        else if (bMaybeCrates && Random.value < 0.35f && iMileMarker > MileMarkerSafetyRange)
        {
            GameObject newDoor = Instantiate(GetRandomDoor());
            Vector3 vDoorPos = vLoc;
            vDoorPos.y += 0.25f + 1.5f;
            newDoor.transform.position = vDoorPos;
            newDoor.transform.parent = transform;
        }

    }

    GameObject GetRandomDoor()
    {
        if( iMileMarker < 60 )
            return prefab_basicDoor;

        float fRando = Random.value;
        if (fRando <= 0.3f)
            return prefab_ladyDoor;

        return prefab_basicDoor;
        
    }

    void PlaceEnemyPrefabAtLocation(Vector3 baddieLocation, GameObject enemyPrefab)
    {
        if (iMileMarker < MileMarkerSafetyRange)
            return;

        GameObject newGo = GameObject.Instantiate(enemyPrefab);
        Vector3 vLoc = baddieLocation;
        float yDelta = 0.55f + newGo.GetComponent<BoxCollider2D>().size.y * 0.5f;
        vLoc.y += yDelta;

        newGo.transform.position = vLoc;
    }


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