package com.terry.engine {
	import flash.display.*;
	import flash.geom.*;
  import flash.events.*;
  import flash.net.*;
	//import flash.filesystem.*;
	import com.terry.engine.util.*;
	
	public class map {
		public static function init():void {
			//Start here!
			mapwidth = 0; mapheight = 0;
			cameratransition = 0; cameratransitionpos = 0; oldcamerax = 0; oldcameray = 0;
			startscriptname = ""; startscript = false;
			camerax = 0; cameray = 0;
			camerapointmode = false; camerapointx = 0; camerapointy = 0;
			stage = ""; level = "";
			tmap.init();
			
			//We init the lookup table:
			var i:int, j:int;
			for (i = 0; i < 100; i++) {
				vmult.push(int(i * 100));
			}
			//We create a blank map 
			for (j = 0; j < 100; j++) {
			  for (i = 0; i < 100; i++) {
				  contents.push(0);
				}
			}
			for (i = 0; i < 2000; i++) {
				directorylisting.push("");
				collisionarray.push(0);
			}
			initcollisionarray();
			
			directorysize = 0;
		}
		
		public static function cameracontrol(t:int = -1):void {
			var i:int, j:int;
			i = obj.getplayer();
			
			if (camerapointmode || i < 0) {
				if (cameratransition > 0) {		
					temp = oldcamerax + (192/2) - (((oldcamerax - ((camerapointx * def.TILESIZE) - (192/2))) * cameratransitionpos) / cameratransition);
					temp2 = oldcameray + (120/2) - (((oldcameray - ((camerapointy * def.TILESIZE) - (120/2))) * cameratransitionpos) / cameratransition);
					centercamera(temp, temp2);
					cameratransitionpos++;
					if (cameratransitionpos >= cameratransition) {
						cameratransition = 0; cameratransitionpos = 0;
					}
				}else{
					centercamera(camerapointx*def.TILESIZE, camerapointy*def.TILESIZE);
				}
			}else{	
				if (cameratransition > 0) {		
					temp = oldcamerax + (192/2) - (((oldcamerax - (obj.entities[i].xp - (192/2))) * cameratransitionpos) / cameratransition);
					temp2 = oldcameray + (120/2) - (((oldcameray - (obj.entities[i].yp - (120/2))) * cameratransitionpos) / cameratransition);
					centercamera(temp, temp2);
					cameratransitionpos++;
					if (cameratransitionpos >= cameratransition) {
						cameratransition = 0; cameratransitionpos = 0;
					}
				}else{
					centercamera(obj.entities[i].xp, obj.entities[i].yp);
				}
			}
		}
		
		public static function changemapsize(x:int, y:int):void {
			mapwidth = x; mapheight = y;
			for (var i:int = 0; i < mapheight; i++) {
				vmult[i] = i * mapwidth;
			}
		}
		
		public static function setrowcollision(t:int):void {
			for (var i:int = 0; i < 20; i++) {
				collisionarray[(t * 20) + i] = 1;
			}
		}
		
		public static function sc(t:int):void { //Set collision
			collisionarray[t] = 1;
		}
		
		public static function initcollisionarray():void {
			//Set collision info for entire map
			sc(2); 
			for (var i:int = 200; i < 600; i++) {
				sc(i);
			}
			collisionarray[480] = 0;
		}
		
	  public static function collide(x:int, y:int):Boolean {
			//which tiles are collidable?
			if (x < 0 || y < 0 || x >= mapwidth || y >= mapheight) return false;
			if (collisionarray[contents[x + vmult[y]]]==1) return true;
			return false;
		}
		
		private static var currentchar:String;
		private static var startindex:int, endindex:int;
		
		public static var currentrow:String;
		public static var currentrowlength:int;
		
		public static function fillcontent():void {
			//tmap is a 30 element array containing 30 strings, 40 characters long
			//need to tokenize each string to extract each 
			for (var j:int = 0; j < mapheight; j++) {
				currentrow = tmap.contents[j]; 
				currentrowlength = currentrow.length;
				
				startindex = 0; endindex = 0;
				var i:int = 0;
				
				//First 39 characters here
				while (endindex < currentrowlength) {
					currentchar = currentrow.substr(endindex, 1);
					if (currentchar == ",") {
						contents[i + vmult[j]] = int(currentrow.substr(startindex, endindex - startindex));
						endindex++;	startindex = endindex;
						i++;
					}
					endindex++;
				}
				//Final character here
				contents[i + vmult[j]] = int(currentrow.substr(startindex, endindex - startindex));
			}
		}
		
		public static function popint():int {
			var t:int;
			//Return the next int from the levelstring
			while (endindex < levelstring.length) {
				currentchar = levelstring.substr(endindex, 1);
				if (currentchar == ",") {
					t = int(levelstring.substr(startindex, endindex - startindex));
					endindex++;	startindex = endindex;
					return t;
				}
				endindex++;
			}
			
			//Didn't find anything
			return 0;
		}
		
		public static function popstring():String {
			var t:String;
			//Return the next int from the levelstring
			while (endindex < levelstring.length) {
				currentchar = levelstring.substr(endindex, 1);
				if (currentchar == ",") {
					t = String(levelstring.substr(startindex, endindex - startindex));
					endindex++;	startindex = endindex;
					return t;
				}
				endindex++;
			}
			
			//Didn't find anything
			return "null";
		}
		
		public static function centercamera(xp:int, yp:int):void {
			camerax = xp - (192/2);
			cameray = yp - (120/2);
			if (camerax < 0) camerax = 0;
			if (cameray < 0) cameray = 0;
			if (camerax > (mapwidth - 25) * def.TILESIZE) camerax = ((mapwidth - 25) * def.TILESIZE) - 1;
			if (cameray > (mapheight - 15) * def.TILESIZE) cameray = ((mapheight - 15) * def.TILESIZE) - 1;
		}
		
		public static function placetile(xp:int, yp:int, t:int):void {
			if (help.inboxw(xp, yp, 0, 0, mapwidth, mapheight)) {
				contents[xp + vmult[yp]] = t;
			}
		}
		
		public static function at(xp:int, yp:int, xoff:int, yoff:int):int {
			xp = xp * def.TILESIZE;
			xp += xoff;
			xoff = xp % def.TILESIZE;
			xp = (xp - xoff) / def.TILESIZE;
			
			yp = yp * def.TILESIZE;
			yp += yoff;
			yoff = yp % def.TILESIZE;
			yp = (yp - yoff) / def.TILESIZE;
			
			if (yp == -1) return at(xp, yp + 1, xoff, yoff);
			if (yp == mapheight) return at(xp, yp - 1, xoff, yoff);
			if (xp == -1) return at(xp + 1, yp, xoff, yoff);
			if (xp == mapwidth) return at(xp - 1, yp, xoff, yoff);
			if (xp >= 0 && yp >= 0 && xp < mapwidth && yp < mapheight) {
				return contents[xp+vmult[yp]];
			}
			return 0;
		}
		
		public static function change(t:String):void {
			//var s:String = help.getroot(t, "_");
			//t = help.getbranch(t, "_");
			var s:String = "movinggame";
			
			obj.removeallblocks();
			
			for (var i:int = 0; i < obj.nentity; i++) {
				//Of course the player's always gonna be object zero, this is just in case
				if (obj.entities[i].rule != "player") obj.entities[i].active = false;
			}
			obj.cleanup();
			
			i = obj.getplayer();
			obj.entities[i].xp = obj.doortox * def.TILESIZE;
			if (t == "apartment") obj.entities[i].xp -= 8;
			obj.entities[i].yp = obj.doortoy * def.TILESIZE;
			obj.entities[i].vx = 0;
			obj.entities[i].vy = 0;
			obj.entities[i].dir = def.UP;
			
			loadlevel(s, t);
		}
		
		//File access
		//public static var file:File, stream:FileStream;
		public static var levelstring:String, levelline:String;
		public static var levelstream:Array, levelstack:int;
		public static var rawdirectorylist:Array;
		public static var directorylisting:Vector.<String> = new Vector.<String>;
		public static var directorysize:int;
		
		public static function createdirectory(s:String, newdir:String):void {
			/*
			//Ok, create directory "newdir" in stage s.
			if (s != stage) stage = s;
			file = File.applicationDirectory;
			if (stage == "") {
				file = file.resolvePath("levels/" + newdir);
			}else {
				file = file.resolvePath("levels/" + stage + "/" + newdir);
			}
			file.createDirectory();
			*/
		}
		
		public static function getdirectorylisting(s:String):void {
			/*
			//Load in a given map
			if (s != stage) stage = s;
			file = File.applicationDirectory;
			if (stage == "") {
				file = file.resolvePath("levels/");
			}else {
				file = file.resolvePath("levels/" + stage + "/");
			}
			
			rawdirectorylist = file.getDirectoryListing();
			directorysize = rawdirectorylist.length;
			for (var i:int = 0; i < directorysize; i++) {
				directorylisting[i] = rawdirectorylist[i].url;//help.getroot(help.getlastbranch(rawdirectorylist[i].url, "/"), ".");
			}
			*/
		}
		
		public static function loadmap(s:String, t:String):void {
			changemapsize(25, 15);
			for (var j:int = 0; j < mapheight; j++) {
				for (var i:int = 0; i < mapwidth; i++) {
					contents[i + vmult[j]] = 0;
				}
			}
			
			if (t == "outside_cold" || t == "outside_warm" || t == "outside_future") {
				tmap.reset();
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,500,500,500,");
				tmap.push("500,500,500,500,500,500,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,500,500,500,");
				tmap.push("500,500,500,500,500,500,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
				tmap.push("500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,");
			}
			
			if (t == "outside_cold") {
				levelimg = 0;
			}else if (t == "outside_warm") {
				levelimg = 1;
			}else if (t == "outside_future") {
				levelimg = 2;
			}else if (t == "apartment") {
				levelimg = -1;
				tmap.reset();
				tmap.push("457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,457,457,457,436,437,437,438,457,457,457,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,436,437,437,383,481,482,403,437,437,438,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,456,500,500,385,501,502,384,500,500,458,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,483,500,500,385,521,522,384,500,500,484,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,503,520,520,405,480,480,404,520,520,504,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,503,485,485,480,480,480,480,480,480,504,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,523,480,480,480,480,480,480,480,480,524,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,386,480,480,480,480,480,480,480,480,387,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,386,480,480,480,480,480,480,480,485,387,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,406,480,480,480,480,480,480,480,485,407,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,476,477,477,477,477,477,477,477,477,478,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,");
				tmap.push("457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,");
			}
			
			fillcontent();
			astar.setmapcollision();
			/*
			if (s != stage) stage = s;
			if (t != level) level = t;
			//Load in a given map
			file = File.applicationDirectory;
			if (stage == "") {
				file = file.resolvePath("levels/" + t + ".txt");
			}else {
				file = file.resolvePath("levels/" + stage + "/" + t + ".txt");
			}
			
			if(file.exists){
				//Convert file to level data
				stream = new FileStream();
				stream.open(file, FileMode.READ);
				levelstring = stream.readUTFBytes(stream.bytesAvailable);
				stream.close();
				
				fillcontent();
			}else {
				//No file exists; blank out contents
				trace("Error: File not found.");
				for (var j:int = 0; j < mapheight; j++) {
					for (var i:int = 0; i < mapwidth; i++) {
						contents[i + vmult[j]] = 1;
					}
				}
			}
			*/
		}
		
		public static function savemap(s:String, t:String):void {
			/*
			var i:int, j:int;
			if (s != stage) stage = s;
			if (t != level) level = t;
      var appDirFile:File;
			if (stage == "") {
				appDirFile = new File("app:/levels/" + t + ".txt");
			}else {
				appDirFile = new File("app:/levels/" + stage + "/" + t + ".txt");
			}
			
      file = new File(appDirFile.nativePath);
			
			//Now output it
			levelstring = "";
			levelstring += String(mapwidth) + "," + String(mapheight) + ",\n";
			for (j = 0; j < mapheight; j++) {
				for (i = 0; i < mapwidth; i++) {
					levelstring += String(contents[i + vmult[j]]);
					levelstring += ",";
				}
				levelstring += "\n";
			}
			
			//Save blocks
			if (obj.nblocks > 0) {
				levelstring += String(obj.activeblocks()) + ",\n";
				for (i = 0; i < obj.nblocks; i++) {
					if (obj.blocks[i].active) {
						levelstring += obj.blocks[i].type + ",";
						levelstring += obj.blocks[i].xp + ",";
						levelstring += obj.blocks[i].yp + ",";
						levelstring += obj.blocks[i].wp + ",";
						levelstring += obj.blocks[i].hp + ",";
						levelstring += obj.blocks[i].trigger + ",";
						levelstring += obj.blocks[i].destx + ",";
						levelstring += obj.blocks[i].desty + ",";
						levelstring += obj.blocks[i].doorname + ",";
						levelstring += "\n";
					}
				}
			}else {
				levelstring += "0,\n";
			}
			
			//Save entities
			if (obj.ninitentities > 0) {
				levelstring += String(obj.ninitentities) + ",\n";
				for (i = 0; i < obj.ninitentities; i++) {
					levelstring += String(obj.initentities[i].xp) + ",";
					levelstring += String(obj.initentities[i].yp) + ",";
					levelstring += obj.initentities[i].type + ",";
					levelstring += obj.initentities[i].para1 + ",";
					levelstring += obj.initentities[i].para2 + ",";
					levelstring += obj.initentities[i].para3 + ",";
				  levelstring += "\n";
				}
			}else{
				levelstring += "0,\n";
			}
			
			stream = new FileStream();
			stream.open(file, FileMode.WRITE);
			stream.writeUTFBytes(levelstring);
			stream.close();
			*/
		}
		
		public static function loadlevel(s:String, r:String):void {
			noxcam = false; noycam = false;
			
			loadmap(s, r);
			
			if (mapwidth <= 25) noxcam = true; 
			if (mapheight <= 15) noycam = true; 
		}
		
		public static var collisionarray:Vector.<int> = new Vector.<int>;
		public static var contents:Vector.<int> = new Vector.<int>;	
		public static var vmult:Vector.<int> = new Vector.<int>;
		public static var temp:int, temp2:int;
		public static var tempstring:String;
		public static var background:int;
		public static var mapwidth:int, mapheight:int;
		public static var noxcam:Boolean, noycam:Boolean;
		
		//Camera
		public static var camerax:int, cameray:int, oldcamerax:int, oldcameray:int;
		public static var cameratransition:int, cameratransitionpos:int;
		public static var camerapointmode:Boolean, camerapointx:int, camerapointy:int;
		
		//External scripting control
		public static var startscriptname:String, startscript:Boolean;
		
		//Levels
		public static var stage:String = "", level:String = "";
		
		public static var levelimg:int;
	}
}