﻿(function ()
{
	var window = this, undefined;

	var dev = false;

	// *** Private Constants ***

	var ANIMATION_INTERVAL = 30;

	var SPRITE_FLOOR_WIDTH = 68;
	var SPRITE_FLOOR_HEIGHT = 62;

	var SPRITE_BOX_WIDTH = 265;
	var SPRITE_BOX_HEIGHT = 250;

	var SPRITE_BOX_SHADOW_WIDTH = 315;
	var SPRITE_BOX_SHADOW_HEIGHT = 268;

	// *** Private Variables ***

	window["Draw"] = {
		// *** Public Constants ***

		ANIM_MERGE: 0,
		ANIM_SPLIT: 1,
		ANIM_MERGE_SPLIT: 2,

		ANIM_BOX_MOVE_XN: 3,
		ANIM_BOX_MOVE_XP: 4,
		ANIM_BOX_MOVE_YN: 5,
		ANIM_BOX_MOVE_YP: 6,

		ANIM_MERGED_BOX_TILT_XN_0: 7,
		ANIM_MERGED_BOX_TILT_XN_1: 8,
		ANIM_MERGED_BOX_TILT_XN_BLOCKED: 9,
		ANIM_MERGED_BOX_ROLL_XN: 10,

		ANIM_MERGED_BOX_TILT_XP_0: 11,
		ANIM_MERGED_BOX_TILT_XP_1: 12,
		ANIM_MERGED_BOX_TILT_XP_BLOCKED: 13,
		ANIM_MERGED_BOX_ROLL_XP: 14,

		ANIM_MERGED_BOX_TILT_YN_0: 15,
		ANIM_MERGED_BOX_TILT_YN_1: 16,
		ANIM_MERGED_BOX_TILT_YN_BLOCKED: 17,
		ANIM_MERGED_BOX_ROLL_YN: 18,

		ANIM_MERGED_BOX_TILT_YP_0: 19,
		ANIM_MERGED_BOX_TILT_YP_1: 20,
		ANIM_MERGED_BOX_TILT_YP_BLOCKED: 21,
		ANIM_MERGED_BOX_ROLL_YP: 22,

		// *** Public Variables ***

		boxAnimInterval: null,

		viewOffsetX: null,
		viewOffsetY: null,

		// *** Functions ***

		build: function ()
		{
			$('gameDiv').innerHTML = '';

			var size, minX = 1000, minY = -1000, maxX = 0, maxY = 0;
			for (var y = 0; y < Level.floor[0].length; y++)
			{
				for (var x = 0; x < Level.floor.length; x++)
				{
					if (Level.floor[x][y] != Level.FLOOR_EMPTY)
					{
						size = Geo.transformBox(x, y);
						if (size.x < minX) { minX = size.x; }
						if (size.y > minY) { minY = size.y; }
						if (size.x > maxX) { maxX = size.x; }
						if (size.y < maxY) { maxY = size.y; }
					}
				}
			}

			this.viewOffsetX = Math.round(($("contentDiv").offsetWidth - (maxX + minX + SPRITE_FLOOR_WIDTH)) / 2);
			this.viewOffsetY = Math.round(($("contentDiv").offsetHeight - (maxY + minY + SPRITE_FLOOR_HEIGHT)) / 2);

			for (var y = 0; y < Level.floor[0].length; y++)
			{
				for (var x = 0; x < Level.floor.length; x++)
				{
					if (Level.floor[x][y] != Level.FLOOR_EMPTY)
					{
						Level.floor[x][y].elem = createFloor(Level.floor[x][y].type, Geo.transformBox(x, y));
					}
				}
			}

			for (var i = 0; i < Level.boxes.length; i++)
			{
				// Create Box
				Level.boxes[i].elem = document.createElement("div");

				// Create Shadow
				Level.boxes[i].elemShadow = document.createElement("div");
				Level.boxes[i].elemShadow.className = 'elemBoxShadow';

				Draw.setBoxPos(i);
				Draw.setBoxStyle(i);

				$("gameDiv").appendChild(Level.boxes[i].elem);
				$("gameDiv").appendChild(Level.boxes[i].elemShadow);
			}

			showHint();
		},

		setBoxPos: function (id)
		{
			var pos = Geo.transformBox(Level.boxes[id].x, Level.boxes[id].y);
			var box = Level.boxes[id].elem;
			var boxShadow = Level.boxes[id].elemShadow;

			box.style.left = (this.viewOffsetX + pos.x - 98)  + 'px';
			box.style.top = (this.viewOffsetY + pos.y - 112)  + 'px';
			box.style.zIndex = (30000 - ((Level.boxes[id].x + Level.boxes[id].y) * 2)) + Level.boxes[id].z;
			// Debug: box.innerHTML = (Level.boxes[id].elem.style.zIndex > 0 ? '<br />' : '') + Level.boxes[id].elem.style.zIndex; // box.style.zIndex;

			if (dev && Level.floor[Level.boxes[id].x] != undefined && Level.floor[Level.boxes[id].x][Level.boxes[id].y] != undefined)
			{
				if (Level.floor[Level.boxes[id].x][Level.boxes[id].y].type == Level.FLOOR_NORMAL)
				{
					Level.floor[Level.boxes[id].x][Level.boxes[id].y].elem.style.backgroundPosition = '0px 0px';
				}
			}

			boxShadow.style.left = (this.viewOffsetX + pos.x - 110)  + 'px';
			boxShadow.style.top = (this.viewOffsetY + pos.y - 118)  + 'px';
			boxShadow.style.zIndex = (20000 - ((Level.boxes[id].x + Level.boxes[id].y) * 2)) + Level.boxes[id].z;
		},
		setBoxStyle: function (id)
		{
if (Level.boxes[id].type == undefined)
{
	// Fehler
     alert("setBoxStyle: " + id);
}

			switch (Level.boxes[id].type)
			{
				case Level.BOX_TYPE_GREEN:
					Level.boxes[id].elem.className = 'elemBoxGreen';
					break;
				case Level.BOX_TYPE_RED:
					Level.boxes[id].elem.className = 'elemBoxRed';
					break;
				case Level.BOX_TYPE_PURPLE:
					Level.boxes[id].elem.className = 'elemBoxPurple';
					break;
				case Level.BOX_TYPE_CYAN:
					Level.boxes[id].elem.className = 'elemBoxCyan';
					break;
				case Level.BOX_TYPE_YELLOW:
					Level.boxes[id].elem.className = 'elemBoxYellow';
					break;
			}

			switch (Level.boxes[id].state)
			{
				case Level.BOX_STATE_ACTIVE:
					this.setBoxSprite(id, 0, 0);
					break;
				case Level.BOX_STATE_INACTIVE:
					this.setBoxSprite(id, 0, 1);
					break;
				case Level.BOX_STATE_UNMOVEABLE:
					this.setBoxSprite(id, 0, 2);
					break;
			}
		},
		setBoxSprite: function (id, x, y)
		{
			Level.boxes[id].elem.style.backgroundPosition = (-SPRITE_BOX_WIDTH * x) + 'px ' + (-SPRITE_BOX_HEIGHT * y) + 'px';
			Level.boxes[id].elemShadow.style.backgroundPosition = (-SPRITE_BOX_SHADOW_WIDTH * x) + 'px ' + (-SPRITE_BOX_SHADOW_HEIGHT * y) + 'px';
		},

		// Returns true on the last frame
		boxAnim: function (box, animType, animFrame, mergedBox)
		{
			switch (animType)
			{
				// Box merging / splitting

				case this.ANIM_MERGE:
					switch (animFrame)
					{
/*
						case 1: this.setBoxSprite(box, 7, 0); break;
						case 2: this.setBoxSprite(box, 7, 1); break;
						case 3: this.setBoxSprite(box, 7, 2); break;
						case 4: this.setBoxSprite(box, 7, 3); break;
						case 5: this.setBoxSprite(box, 7, 4); break;
						case 6: this.setBoxSprite(box, 7, 5); break;
						case 7: this.setBoxSprite(box, 7, 6); break;
						case 8: this.setBoxSprite(box, 7, 7); break;
						case 9:
*/
						default:
							Draw.setBoxStyle(box);
							return true;
					}
					return false;

				case this.ANIM_SPLIT:
					switch (animFrame)
					{
/*
						case 1: this.setBoxSprite(box, 7, 7); break;
						case 2: this.setBoxSprite(box, 7, 6); break;
						case 3: this.setBoxSprite(box, 7, 5); break;
						case 4: this.setBoxSprite(box, 7, 4); break;
						case 5: this.setBoxSprite(box, 7, 3); break;
						case 6: this.setBoxSprite(box, 7, 2); break;
						case 7: this.setBoxSprite(box, 7, 1); break;
						case 8: this.setBoxSprite(box, 7, 0); break;
						case 9:
*/
						default:
							Draw.setBoxStyle(box);
							return true;
					}
					return false;

				case this.ANIM_MERGE_SPLIT:
					var anim1 = this.boxAnim(box, this.ANIM_MERGE, animFrame)
					var anim2 = this.boxAnim(mergedBox, this.ANIM_SPLIT, animFrame);
					return anim1 || anim2;

				// Single Box Rolling

				case this.ANIM_BOX_MOVE_XN:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].x--;
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 1, 7);
							break;
						case 2: this.setBoxSprite(box, 1, 6); break;
						case 3: this.setBoxSprite(box, 1, 5); break;
						case 4: this.setBoxSprite(box, 1, 4); break;
						case 5: this.setBoxSprite(box, 1, 3); break;
						case 6: this.setBoxSprite(box, 1, 2); break;
						case 7: this.setBoxSprite(box, 1, 1); break;
						case 8: this.setBoxSprite(box, 1, 0); break;
						case 9:
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_BOX_MOVE_XP:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 1, 0);
							break;
						case 2: this.setBoxSprite(box, 1, 1); break;
						case 3: this.setBoxSprite(box, 1, 2); break;
						case 4: this.setBoxSprite(box, 1, 3); break;
						case 5: this.setBoxSprite(box, 1, 4); break;
						case 6: this.setBoxSprite(box, 1, 5); break;
						case 7: this.setBoxSprite(box, 1, 6); break;
						case 8: this.setBoxSprite(box, 1, 7); break;
						case 9:
							Level.boxes[box].x++;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_BOX_MOVE_YN:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].y--;
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 2, 7);
							break;
						case 2: this.setBoxSprite(box, 2, 6); break;
						case 3: this.setBoxSprite(box, 2, 5); break;
						case 4: this.setBoxSprite(box, 2, 4); break;
						case 5: this.setBoxSprite(box, 2, 3); break;
						case 6: this.setBoxSprite(box, 2, 2); break;
						case 7: this.setBoxSprite(box, 2, 1); break;
						case 8: this.setBoxSprite(box, 2, 0); break;
						case 9:
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_BOX_MOVE_YP:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 2, 0);
							break;
						case 2: this.setBoxSprite(box, 2, 1); break;
						case 3: this.setBoxSprite(box, 2, 2); break;
						case 4: this.setBoxSprite(box, 2, 3); break;
						case 5: this.setBoxSprite(box, 2, 4); break;
						case 6: this.setBoxSprite(box, 2, 5); break;
						case 7: this.setBoxSprite(box, 2, 6); break;
						case 8: this.setBoxSprite(box, 2, 7); break;
						case 9:
							Level.boxes[box].y++;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);
							return true;
					}
					return false;

				// Multiple Box Rolling

				case this.ANIM_MERGED_BOX_ROLL_XN:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].x--;
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 1, 7);

							Level.boxes[mergedBox].x--;
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 7);
							break;
						case 2: this.setBoxSprite(box, 1, 6); this.setBoxSprite(mergedBox, 1, 6); break;
						case 3: this.setBoxSprite(box, 1, 5); this.setBoxSprite(mergedBox, 1, 5); break;
						case 4: this.setBoxSprite(box, 1, 4); this.setBoxSprite(mergedBox, 1, 4); break;
						case 5: this.setBoxSprite(box, 1, 3); this.setBoxSprite(mergedBox, 1, 3); break;
						case 6: this.setBoxSprite(box, 1, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 7: this.setBoxSprite(box, 1, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 8: this.setBoxSprite(box, 1, 0); this.setBoxSprite(mergedBox, 1, 0); break;
						case 9:
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_XN_0:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = 3;
							this.setBoxPos(box);
							this.setBoxSprite(box, 3, 0);

							Level.boxes[mergedBox].x--;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 7);
							break;
						case 2: this.setBoxSprite(box, 3, 1); this.setBoxSprite(mergedBox, 1, 6); break;
						case 3: this.setBoxSprite(box, 3, 2); this.setBoxSprite(mergedBox, 1, 5); break;
						case 4: this.setBoxSprite(box, 3, 3); this.setBoxSprite(mergedBox, 1, 4); break;
						case 5: this.setBoxSprite(box, 3, 4); this.setBoxSprite(mergedBox, 1, 3); break;
						case 6: this.setBoxSprite(box, 3, 5); this.setBoxSprite(mergedBox, 1, 2); break;
						case 7: this.setBoxSprite(box, 3, 6); this.setBoxSprite(mergedBox, 1, 1); break;
						case 8: this.setBoxSprite(box, 3, 7); this.setBoxSprite(mergedBox, 1, 0); break;
						case 9:
							Level.boxes[box].x -= 2;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_XN_1:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].x -= 2;
							Level.boxes[box].z = -2;
							this.setBoxPos(box);
							this.setBoxSprite(box, 4, 7);

							Level.boxes[mergedBox].x--;
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 7);
							break;
						case 2: this.setBoxSprite(box, 4, 6); this.setBoxSprite(mergedBox, 1, 6); break;
						case 3: this.setBoxSprite(box, 4, 5); this.setBoxSprite(mergedBox, 1, 5); Level.boxes[box].z = 1; this.setBoxPos(box); break;
						case 4: this.setBoxSprite(box, 4, 4); this.setBoxSprite(mergedBox, 1, 4); break;
						case 5: this.setBoxSprite(box, 4, 3); this.setBoxSprite(mergedBox, 1, 3); break;
						case 6: this.setBoxSprite(box, 4, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 7: this.setBoxSprite(box, 4, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 8: this.setBoxSprite(box, 4, 0); this.setBoxSprite(mergedBox, 1, 0); break;
						case 9:
							this.setBoxSprite(box, 0, 2);

							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false

				case this.ANIM_MERGED_BOX_TILT_XN_BLOCKED:
					switch (animFrame)
					{
						case 1:
							this.setBoxSprite(box, 3, 0);

							Level.boxes[mergedBox].x--;
							Level.boxes[mergedBox].z = -2;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 7);
							break;
						case 2: this.setBoxSprite(box, 3, 1); this.setBoxSprite(mergedBox, 1, 6); break;
						case 3: this.setBoxSprite(box, 3, 2); this.setBoxSprite(mergedBox, 1, 5); break;
						case 4: this.setBoxSprite(box, 3, 3); this.setBoxSprite(mergedBox, 1, 4); break;
						case 5: this.setBoxSprite(box, 3, 2); this.setBoxSprite(mergedBox, 1, 5); break;
						case 6: this.setBoxSprite(box, 3, 1); this.setBoxSprite(mergedBox, 1, 6); break;
						case 7: this.setBoxSprite(box, 3, 0); this.setBoxSprite(mergedBox, 1, 7); break;
						case 8:
							this.setBoxSprite(box, 0, 2);

							Level.boxes[mergedBox].x++;
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_ROLL_XP:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 1, 0);

							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 0);
							break;
						case 2: this.setBoxSprite(box, 1, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 3: this.setBoxSprite(box, 1, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 4: this.setBoxSprite(box, 1, 3); this.setBoxSprite(mergedBox, 1, 3); break;
						case 5: this.setBoxSprite(box, 1, 4); this.setBoxSprite(mergedBox, 1, 4); break;
						case 6: this.setBoxSprite(box, 1, 5); this.setBoxSprite(mergedBox, 1, 5); break;
						case 7: this.setBoxSprite(box, 1, 6); this.setBoxSprite(mergedBox, 1, 6); break;
						case 8: this.setBoxSprite(box, 1, 7); this.setBoxSprite(mergedBox, 1, 7); break;
						case 9:
							Level.boxes[box].x++;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].x++;
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_XP_0:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 4, 0);
							
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 1, 0);
							break;
						case 2: this.setBoxSprite(box, 4, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 3: this.setBoxSprite(box, 4, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 4: this.setBoxSprite(box, 4, 3); this.setBoxSprite(mergedBox, 1, 3); break;
						case 5: this.setBoxSprite(box, 4, 4); this.setBoxSprite(mergedBox, 1, 4); break;
						case 6: this.setBoxSprite(box, 4, 5); this.setBoxSprite(mergedBox, 1, 5); break;
						case 7: this.setBoxSprite(box, 4, 6); this.setBoxSprite(mergedBox, 1, 6); Level.boxes[box].z = -2; this.setBoxPos(box); break;
						case 8: this.setBoxSprite(box, 4, 7); this.setBoxSprite(mergedBox, 1, 7); break;
						case 9:
							Level.boxes[box].x += 2;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].x++;
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_XP_1:
					switch (animFrame)
					{
						case 1:
							this.setBoxSprite(box, 1, 0);

							Level.boxes[mergedBox].x += 2;
							Level.boxes[mergedBox].z = 3;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 3, 7);
							break;
						case 2: this.setBoxSprite(box, 1, 1); this.setBoxSprite(mergedBox, 3, 6); break;
						case 3: this.setBoxSprite(box, 1, 2); this.setBoxSprite(mergedBox, 3, 5); break;
						case 4: this.setBoxSprite(box, 1, 3); this.setBoxSprite(mergedBox, 3, 4); break;
						case 5: this.setBoxSprite(box, 1, 4); this.setBoxSprite(mergedBox, 3, 3); break;
						case 6: this.setBoxSprite(box, 1, 5); this.setBoxSprite(mergedBox, 3, 2); break;
						case 7: this.setBoxSprite(box, 1, 6); this.setBoxSprite(mergedBox, 3, 1); break;
						case 8: this.setBoxSprite(box, 1, 7); this.setBoxSprite(mergedBox, 3, 0); break;
						case 9:
							Level.boxes[box].x++;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].z = 1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 2);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_XP_BLOCKED:
					switch (animFrame)
					{
						case 1: this.setBoxSprite(box, 4, 0); this.setBoxSprite(mergedBox, 1, 0); break;
						case 2: this.setBoxSprite(box, 4, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 3: this.setBoxSprite(box, 4, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 4: this.setBoxSprite(box, 4, 3); this.setBoxSprite(mergedBox, 1, 3); break;
						case 5: this.setBoxSprite(box, 4, 2); this.setBoxSprite(mergedBox, 1, 2); break;
						case 6: this.setBoxSprite(box, 4, 1); this.setBoxSprite(mergedBox, 1, 1); break;
						case 7: this.setBoxSprite(box, 4, 0); this.setBoxSprite(mergedBox, 1, 0); break;
						case 8: this.setBoxSprite(box, 0, 2); this.setBoxSprite(mergedBox, 0, 0); return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_ROLL_YN:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].y--;
							this.setBoxPos(box);
							this.setBoxSprite(box, 2, 7);

							Level.boxes[mergedBox].y--;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 2, 7);
							break;
						case 2: this.setBoxSprite(box, 2, 6); this.setBoxSprite(mergedBox, 2, 6); break;
						case 3: this.setBoxSprite(box, 2, 5); this.setBoxSprite(mergedBox, 2, 5); break;
						case 4: this.setBoxSprite(box, 2, 4); this.setBoxSprite(mergedBox, 2, 4); break;
						case 5: this.setBoxSprite(box, 2, 3); this.setBoxSprite(mergedBox, 2, 3); break;
						case 6: this.setBoxSprite(box, 2, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 7: this.setBoxSprite(box, 2, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 8: this.setBoxSprite(box, 2, 0); this.setBoxSprite(mergedBox, 2, 0); break;
						case 9: this.setBoxSprite(box, 0, 0); this.setBoxSprite(mergedBox, 0, 0); return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YN_0:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = 2;
							this.setBoxPos(box);
							this.setBoxSprite(box, 5, 0);

							Level.boxes[mergedBox].y--;
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 2, 7);
							break;
						case 2: this.setBoxSprite(box, 5, 1); this.setBoxSprite(mergedBox, 2, 6); break;
						case 3: this.setBoxSprite(box, 5, 2); this.setBoxSprite(mergedBox, 2, 5); break;
						case 4: this.setBoxSprite(box, 5, 3); this.setBoxSprite(mergedBox, 2, 4); break;
						case 5: this.setBoxSprite(box, 5, 4); this.setBoxSprite(mergedBox, 2, 3); break;
						case 6: this.setBoxSprite(box, 5, 5); this.setBoxSprite(mergedBox, 2, 2); break;
						case 7: this.setBoxSprite(box, 5, 6); this.setBoxSprite(mergedBox, 2, 1); break;
						case 8: this.setBoxSprite(box, 5, 7); this.setBoxSprite(mergedBox, 2, 0); break;
						case 9:
							Level.boxes[box].y -= 2;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YN_1:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].y -= 2;
							Level.boxes[box].z = -3;
							this.setBoxPos(box);
							this.setBoxSprite(box, 6, 7);

							Level.boxes[mergedBox].y--;
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 2, 7);
							break;
						case 2: this.setBoxSprite(box, 6, 6); this.setBoxSprite(mergedBox, 2, 6); break;
						case 3: this.setBoxSprite(box, 6, 5); this.setBoxSprite(mergedBox, 2, 5); break;
						case 4: this.setBoxSprite(box, 6, 4); this.setBoxSprite(mergedBox, 2, 4); Level.boxes[box].z = 0; this.setBoxPos(box); break;
						case 5: this.setBoxSprite(box, 6, 3); this.setBoxSprite(mergedBox, 2, 3); break;
						case 6: this.setBoxSprite(box, 6, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 7: this.setBoxSprite(box, 6, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 8: this.setBoxSprite(box, 6, 0); this.setBoxSprite(mergedBox, 2, 0); break;
						case 9:
							Level.boxes[box].z = 1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 2);
							
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YN_BLOCKED:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = 3;
							this.setBoxPos(box);
							this.setBoxSprite(box, 5, 0);

							Level.boxes[mergedBox].y--;
							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 2, 7);
							break;
						case 2: this.setBoxSprite(box, 5, 1); this.setBoxSprite(mergedBox, 2, 6); break;
						case 3: this.setBoxSprite(box, 5, 2); this.setBoxSprite(mergedBox, 2, 5); break;
						case 4: this.setBoxSprite(box, 5, 3); this.setBoxSprite(mergedBox, 2, 4); break;
						case 5: this.setBoxSprite(box, 5, 2); this.setBoxSprite(mergedBox, 2, 5); break;
						case 6: this.setBoxSprite(box, 5, 1); this.setBoxSprite(mergedBox, 2, 6); break;
						case 7: this.setBoxSprite(box, 5, 0); this.setBoxSprite(mergedBox, 2, 7); break;
						case 8:
							Level.boxes[box].z = 1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 2);

							Level.boxes[mergedBox].y++;
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_ROLL_YP:
					switch (animFrame)
					{
						case 1: this.setBoxSprite(box, 2, 0); this.setBoxSprite(mergedBox, 2, 0); break;
						case 2: this.setBoxSprite(box, 2, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 3: this.setBoxSprite(box, 2, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 4: this.setBoxSprite(box, 2, 3); this.setBoxSprite(mergedBox, 2, 3); break;
						case 5: this.setBoxSprite(box, 2, 4); this.setBoxSprite(mergedBox, 2, 4); break;
						case 6: this.setBoxSprite(box, 2, 5); this.setBoxSprite(mergedBox, 2, 5); break;
						case 7: this.setBoxSprite(box, 2, 6); this.setBoxSprite(mergedBox, 2, 6); break;
						case 8: this.setBoxSprite(box, 2, 7); this.setBoxSprite(mergedBox, 2, 7); break;
						case 9:
							Level.boxes[box].y++;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].y++;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YP_0:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 6, 0);

							Level.boxes[mergedBox].z = -1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 2, 0);
							break;
						case 2: this.setBoxSprite(box, 6, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 3: this.setBoxSprite(box, 6, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 4: this.setBoxSprite(box, 6, 3); this.setBoxSprite(mergedBox, 2, 3); break;
						case 5: this.setBoxSprite(box, 6, 4); this.setBoxSprite(mergedBox, 2, 4); break;
						case 6: this.setBoxSprite(box, 6, 5); this.setBoxSprite(mergedBox, 2, 5); Level.boxes[box].z = -3; this.setBoxPos(box); break;
						case 7: this.setBoxSprite(box, 6, 6); this.setBoxSprite(mergedBox, 2, 6); break;
						case 8: this.setBoxSprite(box, 6, 7); this.setBoxSprite(mergedBox, 2, 7); break;
						case 9:
							Level.boxes[box].y += 2;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].y++;
							Level.boxes[mergedBox].z = 0;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 0);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YP_1:
					switch (animFrame)
					{
						case 1:
							Level.boxes[box].z = -1;
							this.setBoxPos(box);
							this.setBoxSprite(box, 2, 0);

							Level.boxes[mergedBox].y += 2;
							Level.boxes[mergedBox].z = 3;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 5, 7);
							break;
						case 2: this.setBoxSprite(box, 2, 1); this.setBoxSprite(mergedBox, 5, 6); break;
						case 3: this.setBoxSprite(box, 2, 2); this.setBoxSprite(mergedBox, 5, 5); break;
						case 4: this.setBoxSprite(box, 2, 3); this.setBoxSprite(mergedBox, 5, 4); break;
						case 5: this.setBoxSprite(box, 2, 4); this.setBoxSprite(mergedBox, 5, 3); break;
						case 6: this.setBoxSprite(box, 2, 5); this.setBoxSprite(mergedBox, 5, 2); break;
						case 7: this.setBoxSprite(box, 2, 6); this.setBoxSprite(mergedBox, 5, 1); break;
						case 8: this.setBoxSprite(box, 2, 7); this.setBoxSprite(mergedBox, 5, 0); break;
						case 9: 
							Level.boxes[box].y++;
							Level.boxes[box].z = 0;
							this.setBoxPos(box);
							this.setBoxSprite(box, 0, 0);

							Level.boxes[mergedBox].z = 1;
							this.setBoxPos(mergedBox);
							this.setBoxSprite(mergedBox, 0, 2);
							return true;
					}
					return false;

				case this.ANIM_MERGED_BOX_TILT_YP_BLOCKED:
					switch (animFrame)
					{
						case 1: this.setBoxSprite(box, 6, 0); this.setBoxSprite(mergedBox, 2, 0); break;
						case 2: this.setBoxSprite(box, 6, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 3: this.setBoxSprite(box, 6, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 4: this.setBoxSprite(box, 6, 3); this.setBoxSprite(mergedBox, 2, 3); break;
						case 5: this.setBoxSprite(box, 6, 2); this.setBoxSprite(mergedBox, 2, 2); break;
						case 6: this.setBoxSprite(box, 6, 1); this.setBoxSprite(mergedBox, 2, 1); break;
						case 7: this.setBoxSprite(box, 6, 0); this.setBoxSprite(mergedBox, 2, 0); break;
						case 8: this.setBoxSprite(box, 0, 2); this.setBoxSprite(mergedBox, 0, 0); return true;
					}
					return false;
			}

			return true;
		},

		startBoxAnim: function (box, animType, mergedBox)
		{
			if (this.boxAnimInterval == null)
			{
				this.boxAnimInterval = setInterval((function (box, animType, mergedBox)
				{
					var animFrame = 0;

					return function ()
					{
						animFrame++;
						if (Draw.boxAnim(box, animType, animFrame, mergedBox))
						{
							clearInterval(Draw.boxAnimInterval);
							Draw.boxAnimInterval = null;

							showHint();

							if (Game.splitAsSoonAsPossible)
							{
								Game.splitAsSoonAsPossible = !Game.mergeBox(1);
							}
						}
					}
				})(box, animType, mergedBox), ANIMATION_INTERVAL);
			}
		}
	}

	function createFloor(type, pos)
	{
		var elem = document.createElement("div");

		elem.className = 'elemFloor';
		elem.style.left = (Draw.viewOffsetX + pos.x) + 'px';
		elem.style.top = (Draw.viewOffsetY + pos.y) + 'px';
		elem.style.zIndex = 10000 + pos.y;

		switch (type)
		{
			case Level.FLOOR_NORMAL:
				if (dev)
				{
					elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -5) + 'px';
				}
				else
				{
					elem.style.backgroundPosition = '0px 0px';
				}
				break;

			case Level.FLOOR_RED:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -1) + 'px';
				break;

			case Level.FLOOR_PURPLE:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -2) + 'px';
				break;

			case Level.FLOOR_CYAN:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -3) + 'px';
				break;

			case Level.FLOOR_YELLOW:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -4) + 'px';
				break;

			case Level.FLOOR_BRIDGE_OPEN:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -5) + 'px';
				break;

			case Level.FLOOR_BRIDGE_CLOSED:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -6) + 'px';
				break;

			case Level.FLOOR_BROKEN:
				elem.style.backgroundPosition = '0px ' + (SPRITE_FLOOR_HEIGHT * -6) + 'px';
				break;
		}

		$("gameDiv").appendChild(elem);
		return elem;
	}

	function showHint()
	{
		var hash = '';

		switch (Level.currentLevel)
		{
			case 1:
			case 2:
			case 4:
			case 5:
				hash += Level.currentLevel
				for (var i = 0; i < Level.boxes.length; i++)
				{
					hash += ',' + Level.boxes[i].x + ',' + Level.boxes[i].y + ',' + Level.boxes[i].z + ',' + Level.boxes[i].state;
				}
				break;
			default:
				if ($('hintDiv').style.display != 'none') { $('hintDiv').style.display = 'none'; }
				return;
		}

		var img, offsetX, offsetY;
		switch (hash)
		{
			case '1,1,1,0,1,3,1,0,0': img = '001a'; offsetX = -74; offsetY = -180; break;
			case '1,1,1,0,1,2,1,0,0': img = '001b'; offsetX = -84; offsetY = -190; break;
			case '1,1,1,0,0,2,1,0,0': img = '001c'; offsetX = -64; offsetY = -170; break;
			case '1,3,1,1,0,3,1,0,0': img = '001d'; offsetX = -74; offsetY = -180; break;
			case '1,5,1,0,0,4,1,0,0': img = '001e'; offsetX = -84; offsetY = -200; break;

			case '2,3,2,0,0,1,3,0,1': img = '002a'; offsetX = -90; offsetY = -280; break;
			case '2,3,3,0,0,3,3,1,0': img = '002b'; offsetX = -85; offsetY = -250; break;
			case '2,3,2,0,0,3,1,0,0': img = '002c'; offsetX = -90; offsetY = -250; break;

			case '4,2,0,0,0,2,1,0,0': img = '004a'; offsetX = -100; offsetY = -230; break;
			case '4,1,3,0,0,2,3,0,0': img = '004a'; offsetX = -100; offsetY = -230; break;

			case '5,1,1,0,0,0,2,0,1': img = '005a'; offsetX = -100; offsetY = -230; break;
			case '5,2,1,0,0,1,0,0,1': img = '005a'; offsetX = -100; offsetY = -230; break;
			case '5,2,2,0,0,3,1,0,1': img = '005a'; offsetX = -100; offsetY = -230; break;
			case '5,1,2,0,0,2,3,0,1': img = '005a'; offsetX = -100; offsetY = -230; break;

			default:
				if ($('hintDiv').style.display != 'none') { $('hintDiv').style.display = 'none'; }
				return;
		}


		$('hintDiv').style.backgroundImage = 'url(images/hints/' + img + '.png)';
		$('hintDiv').style.left = (Draw.viewOffsetX + offsetX) + 'px';
		$('hintDiv').style.top = (Draw.viewOffsetY + offsetY) + 'px';
		$('hintDiv').style.display = 'block';
	}
})();
