//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Events = {};

Events.List = [];

Events.KeyCodeMap = {
	13 : "Enter",
	16 : "Shift",

	32 : "Space",

	37 : "Left",
	38 : "Up",
	39 : "Right",
	40 : "Down"
};

//=============================================================================
Events.OnInit = function(Canvas) {
	$(Canvas).bind("keydown", Events.OnKeyDown);
	$(Canvas).bind("keyup",   Events.OnKeyUp);
}

//-----------------------------------------------------------------------------
Events.OnKeyDown = function(e) {
	Events.List.push({
		"Type" : "Key Down",
		"Key"  : Events.KeyCodeMap[e.keyCode],
	});

	return false;
}

//-----------------------------------------------------------------------------
Events.OnKeyUp = function(e) {
	Events.List.push({
		"Type" : "Key Up",
		"Key"  : Events.KeyCodeMap[e.keyCode],
	});

	return false;
}

//-----------------------------------------------------------------------------
Events.HasEvents = function() {
	return (Events.List.length > 0);
}

//-----------------------------------------------------------------------------
Events.GetEvent = function() {
	var Temp = Events.List[0];

	Events.List.shift();
	Events.List.pop();
	Events.List.shift();

	return Temp;
}

//=============================================================================
var FPS = {};

FPS.OldTime			= 0;
FPS.LastTime		= 0;

FPS.Count			= 0;
FPS.FramesPerSecond = 0;

FPS.SpeedFactor		= 0;

FPS.OnInit = function() {
	var D = new Date();

	FPS.OldTime	 = D.getTime();
	FPS.LastTime = D.getTime();
}

FPS.OnLoop = function() {
	var D = new Date();

	if(FPS.OldTime + 1000.0 < D.getTime()) {
		FPS.OldTime			= D.getTime();

		FPS.FramesPerSecond = FPS.Count;
		FPS.Count			= 0;
	}

	FPS.SpeedFactor = ((D.getTime() - FPS.LastTime) / 1000.0) * 32.0;
	FPS.LastTime	= D.getTime();

	FPS.Count++;
}

FPS.GetFPS = function() {
	return FPS.FramesPerSecond;
}

FPS.GetSpeedFactor = function() {
	return FPS.SpeedFactor;
}
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Main = {};

Main.Canvas  = null;
Main.Context = null;

Main.Width   = 992;
Main.Height  = 128;

//=============================================================================
Main.OnInit = function() {	
	Main.Canvas  = $("#Game").get(0);
	Main.Context = Main.Canvas.getContext("2d");

	if(Game == undefined) {
		console.log("No Game Object : Bad");
		return;
	}

	FPS.OnInit();

	Events.OnInit(Main.Canvas);

	if(Game.OnInit() == false) {
		console.log("Something went wrong");
		return;
	}

	setTimeout(Main.OnLoop, 1); // Start a Thread... sorta
}

//-----------------------------------------------------------------------------
Main.OnLoop = function() {
	while(Events.HasEvents()) {
		var Event = Events.GetEvent();

		console.log("Event : " + Event.Type + " - " + Event.Key);

		Game.OnEvent(Event);
	}

	Main.Context.clearRect(0, 0, Main.Width, Main.Height);

	Game.OnLoop();
	Game.OnRender(Main.Context);

	FPS.OnLoop();

	setTimeout(Main.OnLoop, 2);
}

//=============================================================================
$(Main.OnInit);

//=============================================================================
var Tracer = {};

Tracer.Hits = [];

Tracer.Calculate = function(StartX, StartY, SpeedX, SpeedY, Width, Height) {
	Tracer.Hits = [];

	var MoveX = SpeedX * FPS.GetSpeedFactor();
	var MoveY = SpeedY * FPS.GetSpeedFactor();

	var StopX = StartX;
	var StopY = StartY;

	var NewX = 0;
	var NewY = 0;

	if(MoveX != 0) {
		if(MoveX >= 0) 	NewX =  FPS.GetSpeedFactor();
		else 			NewX = -FPS.GetSpeedFactor();
	}

	if(MoveY != 0) {
		if(MoveY >= 0) 	NewY =  FPS.GetSpeedFactor();
		else 			NewY = -FPS.GetSpeedFactor();
	}

	if(NewX > 1)	NewX =  1;
	if(NewX < -1)	NewX = -1;
	if(NewY > 1)	NewY =  1;
	if(NewY < -1)	NewY = -1;

	var CollidingX = 0;
	var CollidingY = 0;

	while(true) {
		if(CollidingX == false) {
			if(Tracer.PosValid(StopX + NewX, StopY, Width, Height)) {
				StopX += NewX;
			}else{
				NewX = 0;
				CollidingX = true;
			}
		}

		if(CollidingY == false) {
			if(Tracer.PosValid(StopX, StopY + NewY, Width, Height)) {
				StopY += NewY;
			}else{
				NewY = 0;
				CollidingY = true;
			}
		}

		MoveX += -NewX;
		MoveY += -NewY;

		if(NewX > 0 && MoveX <= 0) NewX = 0;
		if(NewX < 0 && MoveX >= 0) NewX = 0;

		if(NewY > 0 && MoveY <= 0) NewY = 0;
		if(NewY < 0 && MoveY >= 0) NewY = 0;

		if(MoveX == 0) NewX = 0;
		if(MoveY == 0) NewY = 0;

		if(MoveX == 0 && MoveY == 0) 	break;
		if(NewX == 0 && NewY == 0) 		break;
	}

	return {
		"Coords" : {
			"X" : StopX,
			"Y" : StopY
		},

		"Hits" : Tracer.Hits
	};
}

Tracer.PosValid = function(NewX, NewY, Width, Height) {
	var EndX = parseInt(((NewX % 16) + Width)  / 16) + 1;
	var EndY = parseInt(((NewY % 16) + Height) / 16) + 1;

	var Blocked = false;

	var PosX = NewX;
	var PosY = NewY;

	for(var Y = 0;Y < EndY;Y++) {
		for(var X = 0;X < EndX;X++) {
			var MapTile = Map.GetTileType(PosX, PosY);

			// Map Tile is always a hit
			Tracer.Hits.push({
				"Type" : "Tile",
				"TypeID" : MapTile,
				"Coords" : {
					"X" : PosX,
					"Y" : PosY
				}
			});

			if(MapTile == TileTypes.BOX) Blocked = true;

			PosX += 16;
		}

		PosX  = NewX;
		PosY += 16;
	}

	var EntityHits = EntityManager.GetCollisionHits(NewX, NewY, Width, Height);

	if(NewX < 0)			Blocked = true;
	//if(NewY < 0)			Blocked = true;

	if(NewX + Width  > 992) Blocked = true;
	if(NewY + Height > 128) Blocked = true;

	return !Blocked;
}//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var TileTypes = {
	BLANK	: 0,
	BOX		: 1,
	SPIKE	: 2
};

var Tile = function(TileX, TileY, TileID, TypeID) {
	var self	= this;

	var Width	= 16;
	var Height	= 16;

	var X		= TileX * Width;
	var Y		= TileY * Height;

	var SX		= TileID * 16;
	var SY		= 0;

	self.TypeID = TypeID;

	//-------------------------------------------------------------------------
	self.OnRender = function(Context, Tileset) {
		if(Tileset == null)					return;
		if(self.TypeID == TileTypes.BLANK)	return;

		Context.drawImage(Tileset, SX, SY, Width, Height, X, Y, Width, Height);
	}
};

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var SoundManager = {};

SoundManager.List = {};

//=============================================================================
SoundManager.AddSound = function(Name, Filename) {
	SoundManager.List[Name] = new Audio(Filename);
}

//-----------------------------------------------------------------------------
SoundManager.Play = function(Name, Loop) {
	try {
		SoundManager.List[Name].loop = Loop;
		SoundManager.List[Name].play();
	}catch(e) {}
}

//-----------------------------------------------------------------------------
SoundManager.IsReady = function() {
	for(var i in SoundManager.List) {
		if(SoundManager.List[i].readyState != Audio.HAVE_ENOUGH_DATA) return false;
	}

	return true;
}

//-----------------------------------------------------------------------------
SoundManager.Reset = function() {
	SoundManager.List = {};
}

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Orb = function() {
	var self = this;

	var X = 100;
	var Y = 100;

	var Width  = 0;
	var Height = 0;

	var Texture  = null;
	var AnimSets = null;

	//-------------------------------------------------------------------------
	self.OnEvent = function(Event) {
	};

	//-------------------------------------------------------------------------
	self.OnInit = function() {
		Texture = new Image();
		Texture.src = "./js/Orbo/gfx/Orb.png";

		Width  = 12;
		Height = 12;

		AnimSets = new AnimationSets();

		AnimSets.AddSet("Idle",  0, 0, 4, 250);

		AnimSets.SetAnimation("Idle");
	};

	//-------------------------------------------------------------------------
	self.OnLoop = function() {
	};

	//-------------------------------------------------------------------------
	self.OnRender = function(Context) {
		AnimSets.RenderFrame(Context, Texture, X, Y, Width, Height);
	};

	//-------------------------------------------------------------------------
	self.OnInit();
};

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var MetaCipher = function() {
	var self = this;

	var X = 0;
	var Y = 0;

	var Width  = 0;
	var Height = 0;

	var SpeedX = 0;
	var SpeedY = 0;

	var AccelX = 0;
	var AccelY = 0;

	var Texture  = null;
	var AnimSets = null;

	var MoveLeft = false;
	var MoveRight = false;

	var MaxWalkSpeed = 5;
	var CanJump		= true;

	//-------------------------------------------------------------------------
	self.OnEvent = function(Event) {
		if(Event.Type == "Key Down" && Event.Key == "Left")		MoveLeft  = true;
		if(Event.Type == "Key Down" && Event.Key == "Right")	MoveRight = true;

		if(Event.Type == "Key Up" && Event.Key == "Left")		MoveLeft  = false;
		if(Event.Type == "Key Up" && Event.Key == "Right")		MoveRight = false;

		if(Event.Type == "Key Down" && Event.Key == "Space" && CanJump)	SpeedY = -10;
	};

	//-------------------------------------------------------------------------
	self.OnInit = function() {
		Texture = new Image();
		Texture.src = "/Templates/Default/js/Orbo/gfx/MetaCipher.png";

		Width  = 14;
		Height = 14;

		AnimSets = new AnimationSets();

		AnimSets.AddSet("IdleLeft",  0, 0, 1, 50);
		AnimSets.AddSet("IdleRight", 1, 0, 1, 50);
		AnimSets.AddSet("WalkLeft",  2, 0, 2, 100);
		AnimSets.AddSet("WalkRight", 3, 0, 2, 100);

		AnimSets.SetAnimation("WalkLeft");
	};

	//-------------------------------------------------------------------------
	self.OnLoop = function() {
		if(MoveLeft)  {	AccelX = -1; }
		if(MoveRight) {	AccelX =  1; }

		if(!MoveLeft && !MoveRight) {
			AccelX	= 0;
			SpeedX	= 0;
		}

		AccelY = 1; //CConstant.GRAVITY_ACCEL;

		SpeedX += (AccelX * FPS.GetSpeedFactor());
		SpeedY += (AccelY * FPS.GetSpeedFactor());
		
		// Cap our Speed (this should also allow for running)
		if(SpeedX < -MaxWalkSpeed)	SpeedX = -MaxWalkSpeed;
		if(SpeedX > MaxWalkSpeed)	SpeedX = MaxWalkSpeed;

		if(SpeedY > 8) SpeedY = 8;

		var Data = Tracer.Calculate(X, Y, SpeedX, SpeedY, Width, Height);

		if(SpeedY > 0 && Y == Data.Coords.Y) SpeedY = 0;

		X = Data.Coords.X;
		Y = Data.Coords.Y;

		for(var i in Data.Hits) {
			if(Data.Hits[i].Type == "Tile" && Data.Hits[i].TypeID == TileTypes.SPIKE) {
				//X = 0;
				//Y = 0;
			}
		}

		if(MoveLeft)  AnimSets.SetAnimation("WalkLeft");
		if(MoveRight) AnimSets.SetAnimation("WalkRight");
	};

	//-------------------------------------------------------------------------
	self.OnRender = function(Context) {
		AnimSets.RenderFrame(Context, Texture, X, Y, Width, Height);
	};

	//-------------------------------------------------------------------------
	self.OnInit();
};

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Map = {};

Map.Width	= 62;
Map.Height  = 8;

Map.Tileset = null;

Map.Tiles   = {};

//-----------------------------------------------------------------------------
Map.OnLoad = function() {
	Map.Tileset = new Image();
	Map.Tileset.src = "/Templates/Default/js/Orbo/gfx/Tileset.png";

	Map.Tiles = {};

	for(var Y = Map.Height - 1;Y >= 0;Y--) {
		for(var X = 0;X < Map.Width;X++) {
			var TileID = 0;
			var TypeID = 0;

			if(Y >= 7) {
				TileID = (Math.random() * 100) % 3;
			}else
			if(Y > 4) {
				if(Map.Tiles[X][Y + 1].TypeID == TileTypes.BOX) TileID = (Math.random() * 100) % 2;
			}

			TileID = parseInt(TileID);
			TypeID = TileID;

			if(Map.Tiles[X] == undefined) Map.Tiles[X] = {};
			Map.Tiles[X][Y] = new Tile(X, Y, TileID, TypeID);
		}
	}
}

//-----------------------------------------------------------------------------
Map.OnRender = function(Context) {
	for(var X in Map.Tiles) {
		for(var Y in Map.Tiles[X]) {
			Map.Tiles[X][Y].OnRender(Context, Map.Tileset);		
		}
	}
}

//-----------------------------------------------------------------------------
// Real X,Y coords, not Tile X,Y coords
Map.GetTileType = function(X, Y) {
	X = parseInt(X / 16);
	Y = parseInt(Y / 16);

	try {
		return Map.Tiles[X][Y].TypeID;
	}
	catch(e) {
	}

	return TileTypes.BLANK;
}

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var ImageManager = {};

ImageManager.List = {};

//=============================================================================
ImageManager.AddImage = function(Name, Filename) {
	ImageManager.List[Name] = new Image(Filename);
	ImageManager.List[Name].Loaded = false;

	(function() {
		ImageManager.List[Name].onload = function() {
			ImageManager.List[Name].Loaded = true;
		}
	})(Name);
}

//-----------------------------------------------------------------------------
ImageManager.GetImage = function(Name) {
	try {
		return ImageManager.List[Name];
	}
	catch(e) {}

	return null;
}

//-----------------------------------------------------------------------------
ImageManager.IsReady = function() {
	for(var i in ImageManager.List) {
		if(ImageManager.List[i].Loaded == false) return false;
	}

	return true;
}

//-----------------------------------------------------------------------------
ImageManager.Reset = function() {
	ImageManager.List = {};
}

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Hank = {}; /* $.extend({
	OnEvent : function(Event) {
	},

	OnInit : function() {
	},

	OnLoop : function() {
	},

	OnRender : function(Context) {
	}
}, Entity);*/

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Game = {};

//=============================================================================
Game.OnInit = function() {
	Game.Player = new MetaCipher();
	EntityManager.AddEntity(Game.Player);
	//EntityManager.AddEntity(new Orb());

	Map.OnLoad();

	return true;
}

//-----------------------------------------------------------------------------
Game.OnEvent = function(Event) {
	EntityManager.OnEvent(Event);
}

//-----------------------------------------------------------------------------
Game.OnLoop = function() {
	EntityManager.OnLoop();

	$("#GameScore").html("FPS: " + FPS.GetFPS());
}

//-----------------------------------------------------------------------------
Game.OnRender = function(Context) {
	Map.OnRender(Context);

	EntityManager.OnRender(Context);
}

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var EntityManager = {};

EntityManager.List = [];

//=============================================================================
EntityManager.OnEvent = function(Event) {
	for(var i = 0;i < EntityManager.List.length;i++) {
		EntityManager.List[i].OnEvent(Event);
	}
}

//-----------------------------------------------------------------------------
EntityManager.OnLoop = function() {
	for(var i = 0;i < EntityManager.List.length;i++) {
		EntityManager.List[i].OnLoop();
	}
}

//-----------------------------------------------------------------------------
EntityManager.OnRender = function(Context) {
	for(var i = 0;i < EntityManager.List.length;i++) {
		EntityManager.List[i].OnRender(Context);
	}
}

//-----------------------------------------------------------------------------
EntityManager.AddEntity = function(Entity) {
	EntityManager.List.push(Entity);
}

//-----------------------------------------------------------------------------
EntityManager.Reset = function() {
	EntityManager.List = [];
}

//=============================================================================
EntityManager.GetCollisionHits = function(X, Y, Width, Height) {
	var Hits = [];

	for(var i = 0;i < EntityManager.List.length;i++) {
		if(Collider.BoxToBox(X, Y, Width, Height, EntityManager.List[i].X, EntityManager.List[i].Y, EntityManager.List[i].Width, EntityManager.List[i].Height) == true) {
			Hits.push({
				"Type"   : Entity,
				"Entity" : EntityManager.List[i],
				"Coords" : {
					"X" : X,
					"Y" : Y
				}
			});
		}
	}

	return Hits;
}

//=============================================================================
var Entity = {};

/*var Entity = {
	X = 0,
	Y = 0,

	Width  = 0,
	Height = 0,

	SpeedX = 0,
	SpeedY = 0,

	AccelX = 0,
	AccelY = 0,

	Texture  = null,
	AnimSets = null
};*/var Collider = {};

Collider.BoxToBox = function(X, Y, Width, Height, X2, Y2, Width2, Height2) {
	return false;
}//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var AnimationSets = function() {
	var self		= this;

	var Sets		= [];
	var CurrentSet	= null;

	//-------------------------------------------------------------------------
	self.RenderFrame = function(Context, Image, X, Y, Width, Height) {
		if(CurrentSet == null)  return;
		if(!Image)				return;

		var SX = CurrentSet.Column * Width;
		var SY = (CurrentSet.Start + CurrentSet.Animation.GetCurrentFrame()) * Height;

		Context.drawImage(Image, SX, SY, Width, Height, X, Y, Width, Height);
	}

	//-------------------------------------------------------------------------
	self.SetAnimation = function(Name) {
		if(CurrentSet) CurrentSet.Animation.Stop();

		CurrentSet = Sets[Name];

		if(CurrentSet) CurrentSet.Animation.Start();
	}

	//-------------------------------------------------------------------------
	self.AddSet = function(Name, Column, Start, End, Timer) {
		var Anim = new Animation();

		Anim.Timer		= Timer;
		Anim.MaxFrames	= End - Start;

		Sets[Name] = {
			"Animation" : Anim,
			"Column"	: Column,
			"Start"		: Start,
			"End"		: End,
		};
	};
}

//=============================================================================
//=============================================================================
// Tim Jones
// 6/1/2011 7:37 AM
//=============================================================================
var Animation = function() {
	var self		= this;

	var Running		= false;
	var CurrentFrame = 0;

	self.MaxFrames	= 0;
	self.Timer		= 50; //Milliseconds

	//-------------------------------------------------------------------------
	self.Start = function() {
		Running = true;
	};
	
	//-------------------------------------------------------------------------
	self.Stop = function() {
		Running = false;
	};

	//-------------------------------------------------------------------------
	self.GetCurrentFrame = function() {
		return CurrentFrame;
	};

	//-------------------------------------------------------------------------
	var OnLoop = function() {
		if(Running) {
			CurrentFrame++;

			if(CurrentFrame >= self.MaxFrames) CurrentFrame = 0;
		}

		setTimeout(OnLoop, self.Timer);
	};

	//-------------------------------------------------------------------------
	OnLoop();
}

//=============================================================================

