using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DungeonGenerator : MonoBehaviour
{
	public Transform wallSpritePrefab;
	public Transform floor1Prefab;
	public Transform floor2Prefab;
	public Transform floor3Prefab;
	public Transform gratePrefab;
	public Transform elevatorPrefab;
	public Transform ceilingPrefab;
	public Transform spacePrefab;
	public AudioClip useElevator;
	public int elevatorXIndex = -1;
	public int elevatorYIndex = -1;
	public int lastLevel = 7;
	public enum TileType
	{
		Space 	= 0,
		Floor 	= 1,
		Wall 	= 2
	};
	public static int [,]mazeRoom;
	public static int maxDimension = 32;
	public static float tileSize = 0.32f;
	public bool gameInProgress = false;
	void Start ()
	{
		gameInProgress = true;
		generateMaze(maxDimension);
		constructDungeon();//printDungeon();
		placePlayer();
		GameObject.Find("_MinimapCamera").GetComponent<MinimapCamera>().setElevatorMarker();
		EnemyGenerator eg = ((EnemyGenerator)(GameObject.Find("_MasterObject")).GetComponent<EnemyGenerator>());
		eg.spawnEnemies(PlayerPrefs.GetInt("level", 1), 12);
		audio.PlayOneShot(useElevator);
	}
	public void printDungeon ()
	{
		for (int j = 0; j < maxDimension; j++)
		{
			string mazeString = "";
			for (int i = 0; i < maxDimension; i++)
			{
				mazeString += mazeRoom[i, j] + " ";
			}
			Debug.Log(mazeString);
		}
	}
	public void placePlayer ()
	{
		GameObject player = GameObject.Find("_Player");
		for (int j = 0; j < maxDimension; j++)
		{
			for (int i = 0; i < maxDimension; i++)
			{
				if (mazeRoom[i, j] == (int)(TileType.Floor))
				{
					((PlayerControl)player.GetComponent<PlayerControl>()).setTilePosition(i, j);
					return;
				}
			}
		}
	}
	public Transform getRandomFloorTile ()
	{
		Transform prefabTransform = null;	// Eh... never gets returned, but still.
		switch (Random.Range(0, 4))
		{
			case 0:	prefabTransform = floor1Prefab;break;
			case 1:	prefabTransform = floor2Prefab;break;
			case 2:	prefabTransform = floor3Prefab;break;
			case 3:	prefabTransform = gratePrefab;break;
		}
		return prefabTransform;
	}
	public void constructDungeon ()
	{
		GameObject eo = new GameObject("_EnvironmentObjects");
			GameObject ft = new GameObject("_FloorTiles");
				ft.transform.parent = eo.transform;
			GameObject ct = new GameObject("_CeilingTiles");
				ct.transform.parent = eo.transform;
			GameObject wt = new GameObject("_WallTiles");
				wt.transform.parent = eo.transform;
		bool isElevatorPlaced = false;
		/*int level = PlayerPrefs.GetInt("level", 1);
		if (level >= lastLevel)
		{
			isElevatorPlaced = true;	// No elevator on the last floor!
		}*/
		for (int i = 0; i < maxDimension; i++)
		{
			for (int j = 0; j < maxDimension; j++)
			{
				switch ((TileType)mazeRoom[i, j])
				{
					case TileType.Space:
						break;
					case TileType.Floor:
						Transform floorPrefab = getRandomFloorTile();
						if (!isElevatorPlaced)
						{
							isElevatorPlaced = true;
							floorPrefab = elevatorPrefab;
							elevatorXIndex = i;
							elevatorYIndex = j;
						}
						Transform floorTile = (Transform)Instantiate(floorPrefab, new Vector3(i * tileSize, 0.0f, j * tileSize), Quaternion.identity);
						floorTile.rotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f));
						floorTile.position += new Vector3(0.0f, -1.0f * tileSize / 2.0f, 0.0f);
						floorTile.transform.parent = ft.transform;
						Transform ceilingTile = (Transform)Instantiate(ceilingPrefab, new Vector3(i * tileSize, 0.0f, j * tileSize), Quaternion.identity);
						ceilingTile.rotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f));
						ceilingTile.position += new Vector3(0.0f, tileSize / 2.0f - 0.01f, 0.0f);	// Slightly lower than tileSize/2 to fix seam issue!
						ceilingTile.transform.parent = ct.transform;
						break;
					case TileType.Wall:
						// Floor and ceiling tiles.
						// NOTE: Only if we have destructible terrain!
						/*Transform floorWallTile = (Transform)Instantiate(floorPrefab, new Vector3(i * tileSize, 0.0f, j * tileSize + tileSize / 2.0f), Quaternion.identity);
						floorWallTile.rotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f));
						floorWallTile.position += new Vector3(0.0f, -1.0f * tileSize / 2.0f, 0.0f);
						Transform ceilingWallTile = (Transform)Instantiate(ceilingPrefab, new Vector3(i * tileSize, 0.0f, j * tileSize + tileSize / 2.0f), Quaternion.identity);
						ceilingWallTile.rotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f));
						ceilingWallTile.position += new Vector3(0.0f, tileSize / 2.0f - 0.01f, 0.0f);		// Slightly lower than tileSize/2 to fix seam issue!*/
						// Wall side sprites.
						// NOTE: Don't need outer wall sides! But is it easier to to check or to just do it all? xD
						Transform wallSpriteNorth = (Transform)Instantiate(wallSpritePrefab, new Vector3(i * tileSize, 0.0f, j * tileSize + tileSize / 2.0f), Quaternion.identity);
						wallSpriteNorth.rotation = Quaternion.Euler(new Vector3(0.0f, 0.0f, 0.0f));
						wallSpriteNorth.transform.parent = wt.transform;
						Transform wallSpriteSouth = (Transform)Instantiate(wallSpritePrefab, new Vector3(i * tileSize, 0.0f, j * tileSize - tileSize / 2.0f), Quaternion.identity);
						wallSpriteSouth.rotation = Quaternion.Euler(new Vector3(0.0f, 0.0f, 0.0f));
						wallSpriteSouth.transform.parent = wt.transform;
						Transform wallSpriteEast = (Transform)Instantiate(wallSpritePrefab, new Vector3(i * tileSize + tileSize / 2.0f, 0.0f, j * tileSize), Quaternion.identity);
						wallSpriteEast.rotation = Quaternion.Euler(new Vector3(0.0f, 90.0f, 0.0f));
						wallSpriteEast.transform.parent = wt.transform;
						Transform wallSpriteWest = (Transform)Instantiate(wallSpritePrefab, new Vector3(i * tileSize - tileSize / 2.0f, 0.0f, j * tileSize), Quaternion.identity);
						wallSpriteWest.rotation = Quaternion.Euler(new Vector3(0.0f, 90.0f, 0.0f));
						wallSpriteWest.transform.parent = wt.transform;
						break;
				}
			}
		}
	}
	public void generateMaze (int mazeDimension)
	{
		int i, j;
		mazeRoom = new int[maxDimension, maxDimension];
		// Initialize dungeon to all space tiles.
		for (i = 0; i < mazeDimension; i++)
		{
			for (j = 0; j < mazeDimension; j++)
			{
				mazeRoom[i, j] = (int)TileType.Space;
			}
		}
		// Generate floor tiles.
		i = 16;
		j = 16;
		int xPadding = 2;
		int yPadding = 2;
		int chunkSize = 1;
		int level = PlayerPrefs.GetInt("level", 1);
		if (level >= lastLevel)
		{
			chunkSize = 2;
			xPadding = 4;
			yPadding = 4;
		}
		for (int k = 0; k < 256; k++)
		{
			switch (Random.Range(0, 4))		// Begs the question, should the Direction enum be in here instead of PlayerControl? Should it be referenced at all?
			{								// There's no -real- sense of direction in this class; it's all relative.
				case 0:
					if (i > xPadding)
					{
						i -= chunkSize;
					}
					break;
				case 1:
					if (i < mazeDimension - 1 - xPadding)
					{
						i += chunkSize;
					}
					break;
				case 2:
					if (j > yPadding)
					{
						j -= chunkSize;
					}
					break;
				case 3:
					if (j < mazeDimension - 1 - yPadding)
					{
						j += chunkSize;
					}
					break;
			}
			mazeRoom[i, j] = (int)TileType.Floor;
			if (level >= lastLevel)	// Grid the final room!
			{
				mazeRoom[i - 1, j] = (int)TileType.Floor;
				mazeRoom[i, j + 1] = (int)TileType.Floor;
				mazeRoom[i, j - 1] = (int)TileType.Floor;
			}
		}
		// Generate wall tiles.
		for (i = 0; i < mazeDimension; i++)
		{
			for (j = 0; j < mazeDimension; j++)
			{
				if (mazeRoom[i, j] == (int)TileType.Floor)
				{
					if (j - 1 > 0	&&
						mazeRoom[i, j - 1] == (int)TileType.Space)	// North.
					{
						mazeRoom[i, j - 1] = (int)TileType.Wall;
					}
					if (j + 1 < mazeDimension - 1	&&
						mazeRoom[i, j + 1] == (int)TileType.Space)	// South.
					{
						mazeRoom[i, j + 1] = (int)TileType.Wall;
					}
					if (i - 1 > 0	&&
						mazeRoom[i - 1, j] == (int)TileType.Space)	// East.
					{
						mazeRoom[i - 1, j] = (int)TileType.Wall;
					}
					if (i + 1 < mazeDimension - 1	&&
						mazeRoom[i + 1, j] == (int)TileType.Space)	// West.
					{
						mazeRoom[i + 1, j] = (int)TileType.Wall;
					}
				}
			}
		}
	}
}