using UnityEngine;
using System.Collections;

public class LevelGenerator: MonoBehaviour {
	
	static Level.LevelCell[,] ClearLevel (Level.LevelCell[,] cell, int xSize, int ySize){
		for(int i = 0; i < xSize - 0; i++){
			for(int j = 0; j < ySize - 0; j++) {
				cell[i, j] = new Level.LevelCell();
				cell[i, j].type = LevelType.Abyss;
				cell[i, j].u = 31;
				cell[i, j].v = 31;
				cell[i, j].items = null;
			}
		}
		return cell;		
	}
	static int[,] generateRects(int[,] prototype, int xSize, int ySize){
		const int LENGTH = 12;
		int[,] rect = new int[LENGTH, 4];
		for(int z = 0; z < LENGTH; z++) {
			rect[z, 0] = Random.Range(1, xSize - 4);
			rect[z, 1] = Random.Range(1, ySize - 4);
			rect[z, 2] = rect[z, 0] + Random.Range(5, 10);
			rect[z, 3] = rect[z, 1] + Random.Range(5, 10);
		}
		for(int z = 0; z < LENGTH; z++) {
			if (rect[z, 0] != 0)
			for(int y = 0; y < LENGTH; y++) {
				if(z != y) {
					bool flag = false;
					if (rect[z, 0] <= rect[y, 0] && rect[z, 1] <= rect[y, 1] && rect[z, 2] >= rect[y, 0] && rect[z, 3] >= rect[y, 1]) {flag = true;}
					if (rect[z, 0] <= rect[y, 0] && rect[z, 1] <= rect[y, 3] && rect[z, 2] >= rect[y, 0] && rect[z, 3] >= rect[y, 3]) {flag = true;}
					if (rect[z, 0] <= rect[y, 2] && rect[z, 1] <= rect[y, 1] && rect[z, 2] >= rect[y, 2] && rect[z, 3] >= rect[y, 1]) {flag = true;}
					if (rect[z, 0] <= rect[y, 2] && rect[z, 1] <= rect[y, 3] && rect[z, 2] >= rect[y, 2] && rect[z, 3] >= rect[y, 3]) {flag = true;}
					if (flag) {
						rect[y, 0] = 0;
						rect[y, 1] = 0;
						rect[y, 2] = 0;
						rect[y, 3] = 0;
						//Debug.Log("Deleted");
					}
				}
			}
		}
		for(int z = 0; z < LENGTH; z++) {
			if (rect[z, 0] != 0) {
				for(int i = rect[z, 0] + 1; i < xSize - 1 && i < rect[z, 2]; i ++){
				for(int j = rect[z, 1] + 1; j < ySize - 1 && j < rect[z, 3]; j ++){
					prototype[i, j] = z + 3;//1;
				}}
				/*for(int i = rect[z, 0] + 2; i < xSize - 1 && i < rect[z, 2] - 1; i ++){
				for(int j = rect[z, 1] + 2; j < ySize - 1 && j < rect[z, 3] - 1; j ++){
					prototype[i, j] = z + 2;
				}}*/
			}
		}
		return prototype;
	}
	
	public static Level.LevelCell[,] GenerateLevel(int xSize, int ySize, int seed){
		Random.seed = seed;
		Level.LevelCell[,] cell = ClearLevel(new Level.LevelCell[xSize, ySize], xSize, ySize);
		int[,] prototype = new int[xSize, ySize];
		prototype = generateRects(prototype, xSize, ySize);
		
		//Generate single rooms
		for(int i = 0; i < xSize - 1; i++){
			prototype[1, i] = 1;
			prototype[xSize - 2, i] = 1;
			prototype[i, 1] = 1;
			prototype[i, ySize - 2] = 1;
		}
		
		//Generate walls
		for(int z = 0; z < 90; z ++){
			int x = Random.Range(1 , xSize - 1);
			int y = Random.Range(1 , ySize - 1);
			if (Random.Range(0, 2) == 0) {
				if (prototype[x, y] 	== 0 &&
					prototype[x, y + 1] == 0 &&
					prototype[x, y - 1] == 0 &&
					prototype[x, y + 2] == 0 &&
					prototype[x, y - 2] == 0) {
					prototype[x, y] = 1;
					for(int i = x + 1; i < xSize - 1; i++){
						if (prototype[i, y] == 0) {
							prototype[i, y] = 1;
						} else {
							break;
						}							
					}
					for(int i = x - 1; i > 0; i--){
						if (prototype[i, y] == 0) {
							prototype[i, y] = 1;
						} else {
							break;
						}							
					}
				}
			} else {
				if (prototype[x, y] 	== 0 &&
					prototype[x + 1, y] == 0 &&
					prototype[x - 1, y] == 0 &&
					prototype[x + 2, y] == 0 &&
					prototype[x - 2, y] == 0) {
					prototype[x, y] = 1;
					for(int i = y + 1; i < ySize - 1; i++){
						if (prototype[x, i] == 0) {
							prototype[x, i] = 1;
						} else {
							break;
						}							
					}
					for(int i = y - 1; i > 0; i--){
						if (prototype[x, i] == 0) {
							prototype[x, i] = 1;
						} else {
							break;
						}							
					}
				}
			}
		}
		//add walls to rects
		for(int i = 2; i < xSize - 2; i++){
		for(int j = 2; j < ySize - 2; j++) {
			if (prototype[i, j] == 0 && prototype[i, j + 1] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i + 1, j] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i, j - 1] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i - 1, j] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i + 1, j + 1] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i + 1, j - 1] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i - 1, j + 1] > 1){
				prototype[i, j] = 1;	
				}	
			if (prototype[i, j] == 0 && prototype[i - 1, j - 1] > 1){
				prototype[i, j] = 1;	
				}	
		}}
		//mark all
		int cost = 101;
		for(int i = 2; i < xSize - 2; i++){
			for(int j = 2; j < ySize - 2; j++) {
				if (prototype[i, j] == 0) {
					prototype[i, j] = cost;
					if (prototype[i, j + 1] != 1)
						prototype[i, j + 1] = cost;
					if (prototype[i, j - 1] != 1)
						prototype[i, j - 1] = cost;
					if (prototype[i + 1, j] != 1)
						prototype[i + 1, j] = cost;
					if (prototype[i - 1, j] != 1)
						prototype[i - 1, j] = cost;
					
					cost ++;
				} else {
					if (prototype[i, j] != 1) {
						int t = prototype[i, j];
						if (prototype[i, j + 1] != 1)
							prototype[i, j + 1] = t;
						if (prototype[i, j - 1] != 1)
							prototype[i, j - 1] = t;
						if (prototype[i + 1, j] != 1)
							prototype[i + 1, j] = t;
						if (prototype[i - 1, j] != 1)
							prototype[i - 1, j] = t;
					}
				}
			}
		}
		//close fl		
		for(int i = 2; i < xSize - 2; i++)
		for(int j = 2; j < ySize - 2; j++){
			if (prototype[i, j] == 0 &&
				prototype[i + 1, j] == 1 &&
				prototype[i - 1, j] == 1 &&
				prototype[i, j + 1] == 1 &&
				prototype[i, j - 1] == 1) {
				prototype[i, j] = 1;
			}
		}
		//delete mark from center
		for(int i = 2; i < xSize - 2; i++)
		for(int j = 2; j < ySize - 2; j++){
			if ((prototype[i, j + 1] == prototype[i + 1, j] || prototype[i, j + 1] == 0 || prototype[i + 1, j] == 0) &&
				(prototype[i, j - 1] == prototype[i + 1, j] || prototype[i, j - 1] == 0 || prototype[i + 1, j] == 0) &&
				(prototype[i, j - 1] == prototype[i - 1, j] || prototype[i, j - 1] == 0 || prototype[i - 1, j] == 0) &&
				(prototype[i, j + 1] == prototype[i - 1, j] || prototype[i, j + 1] == 0 || prototype[i - 1, j] == 0)) {
				prototype[i, j] = 0;
			}
		}
		//find all marks
		int[] marker = new int[50];
		int maxMark = 0;
		bool marked = false;
		for(int z = 0; z < 50; z++){
			marked = false;
			for(int i = 2; i < xSize - 2; i++){
				for(int j = 2; j < ySize - 2; j++){
					if (prototype[i, j] >= 100){
						bool has = false;
						for (int l = 0; l < maxMark; l++){
							if (marker[l] == prototype[i, j]){
								has = true;
								break;
							}
						}	
						if (!has){
							marker[maxMark] = prototype[i, j];	
							marked = true;
							break;
						}
					}
				}
				if (marked)
					break;
			}
			if (!marked){
				break;
			} else {
				maxMark ++;	
			}
		}
		bool mark = false;
		for(int z = 0; z < maxMark; z++){
			mark = false;
			for(int i = 2; i < xSize - 2; i++){
				for(int j = 2; j < ySize - 2; j++){
					if (prototype[i, j] == marker[z] && prototype[i, j] != 0){
						if (prototype[i, j + 1] == 1 && prototype[i, j + 2] != prototype[i, j] && prototype[i, j + 2] != 0 && prototype[i, j + 2] != 1){
							prototype[i, j + 1] = 2;
							mark = true;
							break;
						}
						if (prototype[i, j - 1] == 1 && prototype[i, j - 2] != prototype[i, j] && prototype[i, j - 2] != 0 && prototype[i, j - 2] != 1){
							prototype[i, j - 1] = 2;
							mark = true;
							break;
						}
						if (prototype[i + 1, j] == 1 && prototype[i + 2, j] != prototype[i, j] && prototype[i + 2, j] != 0 && prototype[i + 2, j] != 1){
							prototype[i + 1, j] = 2;
							mark = true;
							break;
						}
						if (prototype[i - 1, j] == 1 && prototype[i - 2, j] != prototype[i, j] && prototype[i - 2, j] != 0 && prototype[i - 2, j] != 1){
							prototype[i - 1, j] = 2;
							mark = true;
							break;
						}
					}
				}	
				if (mark){
					break;
				}
			}
		}
			for(int i = 2; i < xSize - 2; i++){
				for(int j = 2; j < ySize - 2; j++){
				if (prototype[i, j] == 2 && Random.Range(0, 10) > 1){
					prototype[i, j] = 0;
				}
				if (prototype[i, j] > 2){
					prototype[i, j] = 0;
				}
			}}
		
		/////////////////////////
		
		//mark all
		cost = 101;
		for(int f = 0; f < 3; f++){
			for(int i = 2; i < xSize - 2; i++){
			for(int j = 2; j < ySize - 2; j++) {
				if (prototype[i, j] == 0) {
					prototype[i, j] = cost;
					if (prototype[i, j + 1] != 1 && prototype[i, j + 1] != 2)
						prototype[i, j + 1] = cost;
					if (prototype[i, j - 1] != 1 && prototype[i, j - 1] != 2)
						prototype[i, j - 1] = cost;
					if (prototype[i + 1, j] != 1 && prototype[i + 1, j] != 2)
						prototype[i + 1, j] = cost;
					if (prototype[i - 1, j] != 1 && prototype[i + 1, j] != 2)
						prototype[i - 1, j] = cost;
					
					cost ++;
				} else {
					if (prototype[i, j] != 1 && prototype[i, j] != 2) {
						int t = prototype[i, j];
						if (prototype[i, j + 1] != 1 && prototype[i, j + 1] != 2)
							prototype[i, j + 1] = t;
						if (prototype[i, j - 1] != 1 && prototype[i, j - 1] != 2)
							prototype[i, j - 1] = t;
						if (prototype[i + 1, j] != 1 && prototype[i + 1, j] != 2)
							prototype[i + 1, j] = t;
						if (prototype[i - 1, j] != 1 && prototype[i + 1, j] != 2)
							prototype[i - 1, j] = t;
					}
				}
			}
			}
		}
		//close fl		
		for(int i = 2; i < xSize - 2; i++)
		for(int j = 2; j < ySize - 2; j++){
			if (prototype[i, j] == 0 &&
				prototype[i + 1, j] == 1 &&
				prototype[i - 1, j] == 1 &&
				prototype[i, j + 1] == 1 &&
				prototype[i, j - 1] == 1) {
				prototype[i, j] = 1;
			}
		}
		//delete mark from center
		for(int i = 2; i < xSize - 2; i++)
		for(int j = 2; j < ySize - 2; j++){
			if ((prototype[i, j + 1] == prototype[i + 1, j] || prototype[i, j + 1] == 0 || prototype[i + 1, j] == 0) &&
				(prototype[i, j - 1] == prototype[i + 1, j] || prototype[i, j - 1] == 0 || prototype[i + 1, j] == 0) &&
				(prototype[i, j - 1] == prototype[i - 1, j] || prototype[i, j - 1] == 0 || prototype[i - 1, j] == 0) &&
				(prototype[i, j + 1] == prototype[i - 1, j] || prototype[i, j + 1] == 0 || prototype[i - 1, j] == 0)) {
				prototype[i, j] = 0;
			}
		}
		//find all marks
		marker = new int[50];
		maxMark = 0;
		marked = false;
		for(int z = 0; z < 50; z++){
			marked = false;
			for(int i = 2; i < xSize - 2; i++){
				for(int j = 2; j < ySize - 2; j++){
					if (prototype[i, j] >= 100){
						bool has = false;
						for (int l = 0; l < maxMark; l++){
							if (marker[l] == prototype[i, j]){
								has = true;
								break;
							}
						}	
						if (!has){
							marker[maxMark] = prototype[i, j];	
							marked = true;
							break;
						}
					}
				}
				if (marked)
					break;
			}
			if (!marked){
				break;
			} else {
				maxMark ++;	
			}
		}
		mark = false;
		for(int z = 0; z < maxMark; z++){
			mark = false;
			for(int i = xSize - 2; i >= 2; i--){
				for(int j = ySize - 2; j >= 2; j--){
					if (prototype[i, j] == marker[z] && prototype[i, j] != 0){
						if (prototype[i, j + 1] == 1 && prototype[i, j + 2] != prototype[i, j] && prototype[i, j + 2] != 0 && prototype[i, j + 2] != 1){
							prototype[i, j + 1] = 0;
							mark = true;
							break;
						}
						if (prototype[i, j - 1] == 1 && prototype[i, j - 2] != prototype[i, j] && prototype[i, j - 2] != 0 && prototype[i, j - 2] != 1){
							prototype[i, j - 1] = 0;
							mark = true;
							break;
						}
						if (prototype[i + 1, j] == 1 && prototype[i + 2, j] != prototype[i, j] && prototype[i + 2, j] != 0 && prototype[i + 2, j] != 1){
							prototype[i + 1, j] = 0;
							mark = true;
							break;
						}
						if (prototype[i - 1, j] == 1 && prototype[i - 2, j] != prototype[i, j] && prototype[i - 2, j] != 0 && prototype[i - 2, j] != 1){
							prototype[i - 1, j] = 0;
							mark = true;
							break;
						}
					}
				}	
				if (mark){
					break;
				}
			}
		}
		
		for(int i = 2; i < xSize - 2; i++){
			for(int j = 2; j < ySize - 2; j++){
			if (prototype[i, j] > 2){
				prototype[i, j] = 0;
			}
		}}
		
		
		/////////////
		
		
		
		//Debug.Log(maxMark);
		//paint
		for(int i = 1; i < xSize - 1; i++){
			for(int j = 1; j < ySize - 1; j++) {
				cell[i, j].type = LevelType.Floor;
				cell[i, j].u = 0;
				cell[i, j].v = 0;
				switch (prototype[i, j]){
				case 0:
					break;
				case 1:
					cell[i, j].type = LevelType.Wall;
					break;
				case 2:
					cell[i, j].type = LevelType.ClosedDoor;
					break;
				}/*
				if (prototype[i, j] >= 100) {
					cell[i, j].u = 0;
					cell[i, j].v = 5 + prototype[i, j] % 10;
				} else 
				if (prototype[i, j] >= 2) {
					cell[i, j].u = 1;
					cell[i, j].v = 5 + prototype[i, j] % 10;
				}*/
			}
		}
		int doors = 0;
		for(int i = 1; i < xSize - 1; i++){
			for(int j = 1; j < ySize - 1; j++) {
				switch (cell[i, j].type){
				case LevelType.Wall:
					if (cell[i, j - 1].type == LevelType.Wall || cell[i, j - 1].type == LevelType.ClosedDoor) {
						cell[i, j].u = 1;
						cell[i, j].v = 2;
					} else {
						if (cell[i - 1, j - 1].type == LevelType.Wall) {
							cell[i, j].u = 1;
							cell[i, j].v = 1;
						} else {
							cell[i, j].u = 1;
							cell[i, j].v = 0;
						}
					}						
					break;
				case LevelType.Floor:
					cell[i, j].u = 0;
					cell[i, j].v = 0;
					if (cell[i - 1, j - 1].type == LevelType.Wall && cell[i - 1, j].type == LevelType.Wall){
						cell[i, j].u = 0;
						cell[i, j].v = 2;
					} else 
						if (cell[i - 1, j].type == LevelType.Wall){
							cell[i, j].u = 0;
							cell[i, j].v = 1;
						}
					break;
				case LevelType.ClosedDoor:
					if (cell[i, j - 1].type == LevelType.Wall){
						cell[i, j].u = 2;
						cell[i, j].v = 1;
					} else {
						cell[i, j].u = 2;
						cell[i, j].v = 2;
					}
					cell[i, j].parameter = doors;
					doors ++;
					if (doors > 5) {
						doors = 0;
					}						
					break;
				}
			}
		}
		return cell;
	}

	public static Level.LevelCell[,] CreateDefaultLevel(int XSize, int YSize, int seed){
		Random.seed = seed;
		Level.LevelCell[,] cell = new Level.LevelCell[XSize, YSize];
		for(int i = 0; i < XSize; i++){
			for(int j = 0; j < YSize; j++) {
				cell[i, j] = new Level.LevelCell();
				cell[i, j].type = LevelType.Abyss;
				cell[i, j].u = 3;
				cell[i, j].v = 0;
				cell[i, j].items = null;
			}
		}
		for(int i = 1; i < XSize - 1; i++){
			for(int j = 1; j < YSize - 1; j++) {
				cell[i, j].type = LevelType.Floor;
				cell[i, j].u = 1;
				cell[i, j].v = 1;
				if (Random.Range(0, 7) < 1) {
					cell[i, j].type = LevelType.Wall;
				}
			}
		}
		cell[3, 3].type = LevelType.ClosedDoor;
		cell[3, 3].parameter = 3;
		for(int i = 1; i < XSize - 1; i++){
			for(int j = 1; j < YSize - 1; j++) {
				switch (cell[i, j].type){
				case LevelType.Wall:
					if (cell[i, j - 1].type == LevelType.Wall) {
						cell[i, j].u = 1;
						cell[i, j].v = 1;
					} else {
						cell[i, j].u = 1;
						cell[i, j].v = 0;
					}						
					break;
				case LevelType.Floor:
					cell[i, j].u = 0;
					cell[i, j].v = 0;
					if (cell[i - 1, j - 1].type == LevelType.Wall && cell[i - 1, j].type == LevelType.Wall){
						cell[i, j].u = 0;
						cell[i, j].v = 2;
					} else 
						if (cell[i - 1, j].type == LevelType.Wall){
							cell[i, j].u = 0;
							cell[i, j].v = 1;
						}
					break;
				case LevelType.ClosedDoor:
					cell[i, j].u = 2;
					cell[i, j].v = 0;
					break;
				}
			}
		}
		return cell;
	}
	
	void Update () {
	
	}
}
