using UnityEngine;
using System.Collections;

public class ControlScript : MonoBehaviour {
	
	public Camera cam;
	public TileScript[,] TS = new TileScript[8,6];
	public bool ingame = false;
	public bool win = false;
	public bool lose = false;
	public int gametimer;
	public AudioClip snip,alarm,explode,victory;
	public int countdown = 0;
	public GUISkin gooey;
	public bool deadmessage;
	public bool gotemall = false;

	void Start () {
		GameObject[] search;
		TileScript place;
		search = GameObject.FindGameObjectsWithTag("Tile");
		foreach (GameObject found in search) {
			place = found.GetComponent<TileScript>();
			TS[(int)place.transform.position.x,(int)place.transform.position.z] = place;
		}
		gametimer = 500;
		if (PlayerPrefs.HasKey("state")) {
			if (PlayerPrefs.GetInt ("state") == 1) {
				gametimer = 0;
				lose = true;
				deadmessage = true;
			} else if (PlayerPrefs.GetInt ("state") == 2) {
				gametimer = 0;
				win = true;
				gotemall = true;
			}
		} else {
			PlayerPrefs.SetInt ("state",0);
		}
	}
	
	int CheckFlow(int xx,int yy,int ignoredir,bool flowing) {
		// Insert a starting point and a direction not to check (1 = N, 2 = E, 3 = S, 4 = W)
		// Return total least resistance (in theory)
		
		int resn = 99;
		int rese = 99;
		int ress = 99;
		int resw = 99;
		int minres = 99;
		int flowdir = 0;
		bool navail = false;
		bool eavail = false;
		bool savail = false;
		bool wavail = false;
		
		
		switch (TS[xx,yy].type) {
		case 1:
		case 14:
			eavail = true;
			wavail = true;
			break;
		case 2:
		case 15:
			navail = true;
			savail = true;
			break;
		case 3:
			navail = true;
			eavail = true;
			break;
		case 4:
			eavail = true;
			savail = true;
			break;
		case 5:
			savail = true;
			wavail = true;
			break;
		case 6:
			navail = true;
			wavail = true;
			break;
		case 7:
			eavail = true;
			savail = true;
			wavail = true;
			break;
		case 8:
			navail = true;
			savail = true;
			wavail = true;
			break;
		case 9:
			navail = true;
			eavail = true;
			wavail = true;
			break;
		case 10:
			navail = true;
			eavail = true;
			savail = true;
			break;
		case 11:
		case 16:
			// This is the weird one, we need to make sure the adjacent spaces are valid individually, otherwise it could jump a gap
			if (yy < 5) {
				switch (TS[xx,yy + 1].type) {
				case 2:
				case 4:
				case 5:
				case 7:
				case 8:
				case 10:
				case 11:
				case 13:
				case 15:
					navail = true;
					break;
				}
			}
			if (xx < 7) {
				switch (TS[xx + 1,yy].type) {
				case 1:
				case 5:
				case 6:
				case 7:
				case 8:
				case 9:
				case 11:
				case 12:
				case 14:
					eavail = true;
					break;
				}
			}
			if (yy > 0) {
				switch (TS[xx,yy - 1].type) {
				case 2:
				case 3:
				case 6:
				case 8:
				case 9:
				case 10:
				case 11:
				case 13:
				case 15:
					savail = true;
					break;
				}
			}
			if (xx > 0) {
				switch (TS[xx - 1,yy].type) {
				case 1:
				case 3:
				case 4:
				case 7:
				case 9:
				case 10:
				case 11:
				case 12:
				case 14:
					wavail = true;
					break;
				}
			}
			break;
		case 12:
			if (!TS[xx,yy].cut) {
				eavail = true;
				wavail = true;
			}
			break;
		case 13:
			if (!TS[xx,yy].cut) {
				navail = true;
				savail = true;
			}
			break;
		}
		
		// North check
		if ((yy < 5) && (ignoredir != 1) &&	(navail)) {
			resn = CheckFlow (xx,yy + 1,3,false);
		}
		// East check
		if ((xx < 7) && (ignoredir != 2) &&	(eavail)) {
			rese = CheckFlow (xx + 1,yy,4,false);
		}
		// South check
		if ((yy > 0) && (ignoredir != 3) &&	(savail)) {
			ress = CheckFlow (xx,yy - 1,1,false);
		}
		// West check
		if ((xx > 0) && (ignoredir != 4) &&	(wavail)) {
			resw = CheckFlow (xx - 1,yy,2,false);
		}
		
		if (resn < minres) {
			minres = resn;
			flowdir = 1;
		}
		if (rese < minres) {
			minres = rese;
			flowdir = 2;
		}
		if (ress < minres) {
			minres = ress;
			flowdir = 3;
		}
		if (resw < minres) {
			minres = resw;
			flowdir = 4;
		}
		
		if (flowing) {
			// Actually flow the power instead of just checking it
			int ignored;
			
			if (minres < 99) {
				// It can flow somewhere else, so start flowing
				TS[xx,yy].powered = true;
				switch (flowdir) {
				case 1:
					ignored = CheckFlow (xx,yy + 1,3,true);
					break;
				case 2:
					ignored = CheckFlow (xx + 1,yy,4,true);
					break;
				case 3:
					ignored = CheckFlow (xx,yy - 1,1,true);
					break;
				case 4:
					ignored = CheckFlow (xx - 1,yy,2,true);
					break;
				}
			} else {
				// Just flowed into a dead end, so power it only if it's not a cut wire
				if (!TS[xx,yy].cut) {
					TS[xx,yy].powered = true;
				}
			}
		} else {
			// Just check for power flow
			if (minres == 99) {
				// Dead end, return zero if it's a valid endpoint, or keep at 99 if it's a cut wire
				if ((!TS[xx,yy].cut) && (TS[xx,yy].type >= 16))  {
					minres = 0;
				}
			} else {
				// Add resistance to the minimum resistance if it's a resistor
				if ((TS[xx,yy].type == 14) || (TS[xx,yy].type == 15)) {
					minres += 1;
				}
			}
		}
		
		return minres;
	}
	
	public void ResetPower() {
		// Figure out everything that should be powered now
		// Start by wiping the power grid
		int i,j,ignored;
		int battx = 0;
		int batty = 0;
		
		for (i = 0; i <= 7; i++) {
			for (j = 0; j <= 5; j++) {
				if (TS[i,j].type == 16) {
					// Battery
					TS[i,j].powered = true;
					battx = i;
					batty = j;
				} else {
					// Non-Battery
					TS[i,j].powered = false;
				}
			}
		}
		
		// Start checking power flow from battery
		ignored = CheckFlow (battx,batty,0,true);
		
		int totaltimers = 0;
		for (i = 0; i <= 7; i++) {
			for (j = 0; j <= 5; j++) {
				if ((TS[i,j].powered) && (TS[i,j].type == 18)) {
					lose = true;
					TS[i,j].warning.Play ();
				} else if ((TS[i,j].powered) && (TS[i,j].type == 17)) {
					totaltimers += 1;
				}
			}
		}
		if ((!lose) && (totaltimers == 0)) {
			win = true;
		}
	}
	
	void Update () {
		if ((!win) && (!lose) && (!ingame)) {
			if (Input.GetKeyDown("space")) {
				cam.transform.Rotate(90,0,0);
				ingame = true;
				ResetPower ();
				audio.Play ();
			}
		} else if (win) {
			if (Input.GetKeyDown ("space")) {
				int bombs = PlayerPrefs.GetInt ("bombs");
				bombs += 1;
				PlayerPrefs.SetInt ("bombs",bombs);
				switch (bombs) {
				case 1:
					Application.LoadLevel("puzzle1");
					break;
				case 2:
					Application.LoadLevel("puzzle2");
					break;
				case 3:
					Application.LoadLevel("puzzle3");
					break;
				case 4:
					gotemall = true;
					PlayerPrefs.SetInt ("state",2);
					cam.transform.Rotate(-90,0,0);
					break;
				}
			}
		}
	}
	
	void OnGUI() {
		GUI.skin = gooey;
		if ((ingame) && (countdown != 500)) {
        	GUI.Box(new Rect(0, 0, Screen.width, 100), ((gametimer / 50) + 1).ToString ());
		} else if ((deadmessage) && (countdown <= 0)) {
			GUI.Box(new Rect(0, (Screen.height / 2) - 50, Screen.width, 100), "You are dead.");
		} else if ((!win) && (!lose)) {
			GUI.Box(new Rect(0, (Screen.height / 2) - 50, Screen.width, 100), "Press Space to start.");
		} else if (gotemall) {
			GUI.Box(new Rect(0, (Screen.height / 2) - 50, Screen.width, 100), "You win!");
		} else if (win) {
			GUI.Box(new Rect(0, 0, Screen.width, 100), "Press Space to continue.");
		}
    }
	
	void FixedUpdate () {
		if (countdown > 0) {
			countdown -= 1;
			if (countdown <= 0) {
				if ((lose) && (!deadmessage)) {
					AudioSource.PlayClipAtPoint (explode,transform.position);
					audio.Stop ();
					cam.transform.Rotate(-90,0,0);
					deadmessage = true;
					countdown = 150;
				}
			}
		}
		if ((lose) && (ingame)) {
			gametimer = 0;
			ingame = false;
			AudioSource.PlayClipAtPoint (alarm,transform.position);
			countdown = 100;
			PlayerPrefs.SetInt ("state",1);
		}
		if ((win) && (ingame)) {
			ingame = false;
			audio.Stop ();
			AudioSource.PlayClipAtPoint (victory,transform.position);
			countdown = 200;
		}
		if (ingame) {
			gametimer -= 1;
			if (gametimer <= 0) {
				int i,j;
				for (i = 0; i <= 7; i++) {
					for (j = 0; j <= 5; j++) {
						if ((TS[i,j].powered) && (TS[i,j].type == 17)) {
							lose = true;
							TS[i,j].warning.Play ();
						}
					}
				}
				lose = true;
				ingame = false;
				AudioSource.PlayClipAtPoint (alarm,transform.position);
				countdown = 100;
				PlayerPrefs.SetInt ("state",1);
			}
		}
	}
}
