//Map cell struct
public struct cell{
	public char visual;
	public int current;
	public int x;
	public int y;
	public int generated;
	public string roomName;
	//0 Not on grid edge //1 left edge //2 top edge //3 right edge //4 bottom edge
	//5 TOP LEFT corner //6 TOP RIGHT corner //7 BOTTOM RIGHT corner //8 BOTTOM LEFT corner 
	public int gridEdge;
	public int visited; //when grombo has been to a room;
}

public class MapGeneration : MonoBehaviour{
	//Door Variables
	private GameObject leftDoor;
	private GameObject topDoor;
	private GameObject rightDoor;
	private GameObject bottomDoor;
	private DoorScriptL left; //these all used to be DoorScript but the subclass made me change it
	private DoorScriptT top;
	private DoorScriptR right;
	private DoorScriptB bottom;
	private string pastRoom = "NoRoomYet";
	
	//Room List Variables
	private LinkedList roomList = new LinkedList();
	private int counter = 0;
	
	//Initializing Grid Variables
	private int height = 7;
	private int width = 7;
	private int startPosH = 3;
	private int startPosW = 3;

	//Complex Grid Variables
	private int desiredRoomCount = 6;
	private int currentRoomCount = 0;
	public cell[,] grid;
	private cell currentLocation;
	
    public void Start(){
		leftDoor = GameObject.FindGameObjectWithTag("LeftDoor");
		topDoor = GameObject.FindGameObjectWithTag("TopDoor");
		rightDoor = GameObject.FindGameObjectWithTag("RightDoor");
		bottomDoor = GameObject.FindGameObjectWithTag("BottomDoor");
		left = leftDoor.GetComponent(); //SubClass made me change these
		top = topDoor.GetComponent();
		right = rightDoor.GetComponent();
		bottom = bottomDoor.GetComponent();
		listInitialize();
		//listPrint();
		Random.InitState((int)System.DateTime.Now.Ticks);
		gridInitialize();
		gridFill();
		grid[startPosH, startPosW].current = 1;
		currentRoomCount = 0;
		gridFill();
		assignSpecialRooms();
        gridPrint();
		doorSpawn();
    }

    public void Update(){
		if(pastRoom != SceneManager.GetActiveScene().name){
			doorSpawn();
			pastRoom = SceneManager.GetActiveScene().name;
		}
    }
	
	public void gridInitialize(){
		grid = new cell[height, width];
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				grid[i, j].y = i;
				grid[i, j].x = j;
				grid[i, j].gridEdge = 0;
				grid[i, j].generated = 0;
				grid[i,j].visited = 0; //new line
				if(i == startPosH && j == startPosW){
					grid[i, j].visual = 'S';
					grid[i,j].current = 1;
					grid[i, j].generated = 1;
					grid[i, j].roomName = "Demo_Start";
				}else{					
					grid[i, j].visual = '0';
					grid[i, j].current = 0;
				}
				if(i == 0){
					grid[i, j].gridEdge = 2;
				}
				if(i == height - 1){
					grid[i, j].gridEdge = 4;
				}
				if(j == 0){
					grid[i, j].gridEdge = 1;
				}
				if(j == width - 1){
					grid[i, j].gridEdge = 3;
				}
				if(i == 0 && j == 0 ){
					grid[i, j].gridEdge = 5;
				}
				if(i == height - 1 && j == 0){
					grid[i, j].gridEdge = 8;
				}
				if(i == height - 1 && j == width - 1){
					grid[i, j].gridEdge = 7;
				}
				if(i == 0 && j == width - 1){
					grid[i, j].gridEdge = 6;
				}
			}
		}
	}
	
	private void gridFill(){
		int release = 0;
		cell place;
		place.x = -1;
		place.y = -1;
		place.gridEdge = 0;
		place.generated = 0;
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				if(grid[i, j].current == 1){
					place = grid[i, j];

				}
			}
		}
		while(currentRoomCount != desiredRoomCount){
			int randNum = 5;
			release++;
			if(release == 100){
				break;
			}
			while(randNum == 5){
				randNum = Random.Range(1,5);
			}
			if((place.gridEdge != 1 && place.gridEdge != 5 && place.gridEdge != 8) && randNum == 1){
				if(grid[place.y, place.x - 1].generated == 0){
					grid[place.y, place.x - 1].current = 1;
					grid[place.y, place.x - 1].visual = 'R';
					grid[place.y, place.x - 1].generated = 1;
					grid[place.y, place.x - 1].roomName = assignRoom();
					place.current = 0;
					place = grid[place.y, place.x - 1];
					currentRoomCount++;
				}
				continue;
			}
			if((place.gridEdge != 2 && place.gridEdge != 5 && place.gridEdge != 6) && randNum == 2){
				if(grid[place.y - 1, place.x].generated == 0){
					grid[place.y - 1, place.x].current = 1;
					grid[place.y - 1, place.x].visual = 'R';
					grid[place.y - 1, place.x].generated = 1;
					grid[place.y - 1, place.x].roomName = assignRoom();
					place.current = 0;
					place = grid[place.y - 1, place.x];
					currentRoomCount++;
				}
				continue;
			}
			if((place.gridEdge != 3  && place.gridEdge != 6 && place.gridEdge != 7) && randNum == 3){
				if(grid[place.y, place.x + 1].generated == 0){
					grid[place.y, place.x + 1].current = 1;
					grid[place.y, place.x + 1].visual = 'R';
					grid[place.y, place.x + 1].generated = 1;
					grid[place.y, place.x + 1].roomName = assignRoom();
					place.current = 0;
					place = grid[place.y, place.x + 1];
					currentRoomCount++;
				}
				continue;
			}
			if((place.gridEdge != 4 && place.gridEdge != 7 && place.gridEdge != 8) && randNum == 4){
				if(grid[place.y + 1, place.x].generated == 0){
					grid[place.y + 1, place.x].current = 1;
					grid[place.y + 1, place.x].visual = 'R';
					grid[place.y + 1, place.x].generated = 1;
					grid[place.y + 1, place.x].roomName = assignRoom();
					place.current = 0;
					place = grid[place.y + 1, place.x];
					currentRoomCount++;
				}
				continue;
			}
		}
	}
	
	private void assignSpecialRooms(){
		int end = 0;
		int randNum = 5;
		while(randNum == 5){
			randNum = Random.Range(1,5);
		}
		randNum = 4;
		switch(randNum){
			case 1:
				for(int i = 0; i < height; i++){
					for(int j = 0; j < width; j++){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i, j].visual != 'S'){
								grid[i, j].visual = 'B';
								grid[i, j].roomName = "Demo_Boss";
								end = 1;
							}
						}
						
					}
				}
				end = 0;
				for(int i = height - 1; i >= 0; i--){
					for(int j = width - 1; j >=0; j--){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i,j].visual != 'S'){
								grid[i, j].visual = 'I';
								grid[i, j].roomName = "Demo_Shopkeeper";
								end = 1;
							}
						}
						
					}
				}
				break;
			case 2:
				for(int i = 0; i < height; i++){
					for(int j = width - 1; j >= 0; j--){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i, j].visual != 'S'){
								grid[i, j].visual = 'B';
								grid[i, j].roomName = "Demo_Boss";
								end = 1;
							}
						}
						
					}
				}
				end = 0;
				for(int i = height - 1; i >= 0; i--){
					for(int j = 0; j < width; j++){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i,j].visual != 'S'){
								grid[i, j].visual = 'I';
								grid[i, j].roomName = "Demo_Shopkeeper";
								end = 1;
							}
						}
						
					}
				}
				break;
			case 3:
			for(int i = height - 1; i >= 0; i--){
					for(int j = width - 1; j >= 0; j--){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i, j].visual != 'S'){
								grid[i, j].visual = 'B';
								grid[i, j].roomName = "Demo_Boss";
								end = 1;
							}
						}
						
					}
				}
				end = 0;
				for(int i = 0; i < height; i++){
					for(int j = 0; j < width; j++){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i,j].visual != 'S'){
								grid[i, j].visual = 'I';
								grid[i, j].roomName = "Demo_Shopkeeper";
								end = 1;
							}
						}
						
					}
				}
				break;
			case 4:
			for(int i = height - 1; i >= 0; i--){
					for(int j = 0; j < width; j++){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i, j].visual != 'S'){
								grid[i, j].visual = 'B';
								grid[i, j].roomName = "Demo_Boss";
								end = 1;
							}
						}
						
					}
				}
				end = 0;
				for(int i = 0; i < height; i++){
					for(int j = width - 1; j >= 0; j--){
						if(end == 1){
							break;
						}
						if(grid[i, j].generated == 1){
							if(grid[i,j].visual != 'S'){
								grid[i, j].visual = 'I';
								grid[i, j].roomName = "Demo_Shopkeeper";
								end = 1;
							}
						}
						
					}
				}
				break;
			default:
				Debug.Log("Something Has gone wrong");
				break;
		}
	}
	
	public void gridPrint(){
		int x = 1;
		string rowP = x + "     ";
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				rowP += grid[i, j].visual;
				rowP += "     ";
			}
			Debug.Log(rowP);
			x++;
		rowP = x + "     ";
		}
	}
	//Currenlty the list in in a modified state for the demo
	private void listInitialize(){
		string addit = "Demo6";
		listAdd(addit);
		addit = "Demo7";
		listAdd(addit);
		addit = "Demo8";
		listAdd(addit);
		addit = "Demo9";
		listAdd(addit);
		addit = "Demo10";
		listAdd(addit);
		addit = "Demo11";
		listAdd(addit);
		addit = "Demo12";
		listAdd(addit);
		addit = "Demo13";
		listAdd(addit);
		addit = "Demo14";
		listAdd(addit);
		addit = "Demo15";
		listAdd(addit);
		addit = "Demo16";
		listAdd(addit);
		addit = "Demo17";
		listAdd(addit);
		addit = "Demo18";
		listAdd(addit);
		addit = "Demo19";
		listAdd(addit);
		addit = "Demo20";
		listAdd(addit);
		addit = "Demo_Enemy";
		listAdd(addit);
		addit = "Demo_Enemy2";
		listAdd(addit);
		/*
		addit = "IanTestRoom15";
		listAdd(addit);
		addit = "IanTestRoom16";
		listAdd(addit);
		addit = "IanTestRoom17";
		listAdd(addit);
		addit = "IanTestRoom18";
		listAdd(addit);
		addit = "IanTestRoom19";
		listAdd(addit);
		addit = "IanTestRoom20";
		listAdd(addit);
		*/
	}
	
	private void listAdd(string addit){
		roomList.AddLast(addit);
		counter++;
	}
	
	private void listPrint(){
		        foreach (string value in roomList)
        {
            Debug.Log(value);
        }
	}
	//Currently Casey's demo rooms are implemented as the assigned rooms
	private string assignRoom(){
		int selector = Random.Range(1,counter);
		LinkedListNode node = roomList.First;
		for(int i = 0; i < selector - 1; i++){
			node = node.Next;
		}
		counter--;
		string assignment = node.Value;
		roomList.Remove(assignment);
		//Debug.Log(assignment);
		return assignment;
	}
	
	private void doorSpawn(){
		currentLocation.x = 6;
		currentLocation.y = 6;
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				//Debug.Log(grid[i,j].roomName);
				if(grid[i, j].roomName == SceneManager.GetActiveScene().name){
					grid[i,j].visited = 1; //new line
					currentLocation = grid[i, j];
				}
			}
		}
		//Debug.Log(currentLocation.x);
		//Debug.Log(currentLocation.y);
		if(grid[currentLocation.y, currentLocation.x].gridEdge != 1 && grid[currentLocation.y, currentLocation.x].gridEdge != 5 && grid[currentLocation.y, currentLocation.x].gridEdge != 8){
			if(grid[currentLocation.y, currentLocation.x - 1].generated == 1){ 
				leftDoor.SetActive(true);
				//Debug.Log(grid[currentLocation.y, currentLocation.x - 1].roomName);
				left.destination = grid[currentLocation.y, currentLocation.x - 1].roomName;
			}else{
				leftDoor.SetActive(false);
			}
		}else{
			leftDoor.SetActive(false);
		}
		if(grid[currentLocation.y, currentLocation.x].gridEdge != 2  && grid[currentLocation.y, currentLocation.x].gridEdge != 5 && grid[currentLocation.y, currentLocation.x].gridEdge != 6){
			if(grid[currentLocation.y - 1, currentLocation.x].generated == 1){
				topDoor.SetActive(true);
				//Debug.Log(grid[currentLocation.y - 1, currentLocation.x].roomName);
				top.destination = grid[currentLocation.y - 1, currentLocation.x].roomName;
			}else{
				topDoor.SetActive(false);
			}
		}else{
			topDoor.SetActive(false);
		}
		if(grid[currentLocation.y, currentLocation.x].gridEdge != 3  && grid[currentLocation.y, currentLocation.x].gridEdge != 6 && grid[currentLocation.y, currentLocation.x].gridEdge != 7){
			if(grid[currentLocation.y, currentLocation.x + 1].generated == 1){
				rightDoor.SetActive(true);
				//Debug.Log(grid[currentLocation.y, currentLocation.x + 1].roomName);
				right.destination = grid[currentLocation.y, currentLocation.x + 1].roomName;
			}else{
				rightDoor.SetActive(false);
			}
		}else{
			rightDoor.SetActive(false);
		}
		if(grid[currentLocation.y, currentLocation.x].gridEdge != 4  && grid[currentLocation.y, currentLocation.x].gridEdge != 7 && grid[currentLocation.y, currentLocation.x].gridEdge != 8){
			if(grid[currentLocation.y + 1, currentLocation.x].generated == 1){
				bottomDoor.SetActive(true);
				//Debug.Log(grid[currentLocation.y + 1, currentLocation.x].roomName);
				bottom.destination = grid[currentLocation.y + 1, currentLocation.x].roomName;
			}else{
				bottomDoor.SetActive(false);
			}
		}else{
			bottomDoor.SetActive(false);
		}
	}

	public int retH(){
		return height;
	}
	
	public int retW(){
		return width;
	}
	
	public int retSX(){
		return startPosW;
	}
	
	public int retSY(){
		return startPosH;
	}
	
	public int retDesiredRooms(){
		return desiredRoomCount;
	}
	
	public void setH(int val){
		height = val;
	}
	
	public void setW(int val){
		width = val;
	}
}