﻿//window.onload = function(){
//        Puzzle.init(document.getElementById("puzzle"), "Puzzle/puzzle.jpg", {w:80, h:80});
//        
//        
//				Puzzle.onTime = function(ms)
//				{
//				var txtTime = document.getElementById("txtTime");
//				txtTime.value = GetTime(ms);
//				}
//				Puzzle.onComplete = function(ms)
//				{
//					alert("Gone in " + GetTime(ms));
//					Puzzle.stop();
//				}

//        Puzzle.start();

//    };
var Puzzle = {
	puzFrame : null,
	c : 0,
	r : 0,
	fw : 0,
	fh : 0,
	bsz : null,
	blks : null,
	started : false,
	img : null,
	moves : 0,
	startTime : 0,
	timerID : null,
	bar : null,
	init : function(frame, puzFile, size)
	{
		if ((frame === null) && (Puzzle.puzFrame === null)) { return; }

		if (Puzzle.puzFrame === null)
		{
			Puzzle.fw = getW(frame);
			Puzzle.fh = getH(frame);
			Puzzle.puzFrame = document.createElement("div");
			frame.appendChild(Puzzle.puzFrame);
			Puzzle.puzFrame.style.background = "transparent";
			Puzzle.puzFrame.style.position = "relative";
			Puzzle.puzFrame.style.width = Puzzle.fw + "px";
			Puzzle.puzFrame.style.height = Puzzle.fh + "px";
			Puzzle.onMove = new Function();
			Puzzle.onComplete = new Function();
			Puzzle.onTime = new Function();
		}
		
//		Puzzle.bar = document.createElement("img");
//		Puzzle.bar.src = "./images/bar.gif";
//		Puzzle.puzFrame.appendChild(Puzzle.bar);
//		Puzzle.bar.style.marginLeft = "auto";
//		Puzzle.bar.style.marginRight = "auto";
//		Puzzle.bar.style.zIndex = "500";
//		setX(Puzzle.bar, Puzzle.fw/2 - 110);
//		setY(Puzzle.bar, Puzzle.fh/2 - 10);
//		Puzzle.bar.style.position = "absolute";
//		Puzzle.showTimeBar(true);
		
		Puzzle.img = puzFile;
		Puzzle.bsz = {w:size.w, h:size.h};
		Puzzle.r = Math.floor(Puzzle.fh / Puzzle.bsz.h);
		Puzzle.c = Math.floor(Puzzle.fw / Puzzle.bsz.w);
		Puzzle.blks = [Puzzle.c*Puzzle.r];
		for (var i = 0; i < Puzzle.r; i++)
		{
			for (var j = 0; j < Puzzle.c; j++)
			{
				var b = document.createElement("div");
				Puzzle.puzFrame.appendChild(b);
				b.style.background = "url(" + puzFile + ") no-repeat top left";
				b.style.position = "absolute";
				b.style.borderTop= "solid 1px #c0c0c0";
				b.style.borderLeft= "solid 1px #c0c0c0";
				
				var by = i * Puzzle.bsz.h;
				var bx = j * Puzzle.bsz.w;
				
				b.style.zIndex = b.i = b.ci = i*Puzzle.c + j;
				Puzzle.blks[b.i] = {x : bx, y : by, blk : b};
				b.style.backgroundPosition = (-bx) + "px " + (-by) + "px";

				b.style.width = Puzzle.bsz.w + "px";
				b.style.height = Puzzle.bsz.h + "px";
				setX(b, bx);
				setY(b, by);
			}
		}
		
		if (window.opera) { document.body.style.background = document.body.style.background; }

//		Puzzle.showTimeBar(false);
	},
	
//	showTimeBar : function(show)
//	{
//		if (show)
//		{
//			Puzzle.bar.style.display = "inline";
//			Puzzle.bar.style.visibility = "visible";
//			Puzzle.bar.style.zIndex = "500";
//		}
//		else
//		{
//			Puzzle.bar.style.display = "none";
//			Puzzle.bar.style.hidden = "visible";
//			Puzzle.bar.style.zIndex = "0";
//		}
//	},
	
	dragStartEvt : function()
	{
		Drag.obj.style.zIndex = 400;
	},
	
	dragEndEvt : function(nx, ny)
	{
		var ex = nx + Puzzle.bsz.w/2;
		var ey = ny + Puzzle.bsz.h/2;
		Drag.obj.style.zIndex = 0;
		
		var ii = 0;
		ii = Math.floor(ex / Puzzle.bsz.w);
		var jj = 0;
		jj = Math.floor(ey / Puzzle.bsz.h);
		var dropBlk = Puzzle.blks[jj*Puzzle.c + ii];
		var dragBlk = Puzzle.blks[this.ci];
		Puzzle.swop(dropBlk, dragBlk);
		Puzzle.moves++;
		if (Puzzle.onMove) Puzzle.onMove(Puzzle.moves);
		
		if (Puzzle.isSolved())
		{
			Puzzle.stop();
			Puzzle.onComplete(Puzzle.calcTime());
		}
	},

	isSolved : function()
	{
		for (var i = 0; i < Puzzle.blks.length; i++)
		{
			if (Puzzle.blks[i].blk.ci !== Puzzle.blks[i].blk.i) return false;
		}
		return true;
	},
	
	swop : function(b1, b2)
	{
		var blk = {x: b1.x, y: b1.y, blk: b1.blk, ci : b1.blk.ci};
		b1.blk.style.zIndex = b1.blk.ci = b2.blk.ci;
		setX(b1.blk, b2.x);
		setY(b1.blk, b2.y);
		
		b2.blk.style.zIndex = b2.blk.ci = blk.ci;
		setX(b2.blk, blk.x);
		setY(b2.blk, blk.y);

		b1.blk = b2.blk;
		b2.blk = blk.blk;
	},
	
	start : function()
	{
//		Puzzle.showTimeBar(true);
//		Puzzle.started = false;
		
		Puzzle.scramble();
		for (var i = 0; i < Puzzle.blks.length; i++)
		{
			var b = Puzzle.blks[i].blk;
			Drag.init(b, null, 0, Puzzle.fw - Puzzle.bsz.w, 0, Puzzle.fh - Puzzle.bsz.h);
			b.onDragStart = Puzzle.dragStartEvt;
			b.onDragEnd = Puzzle.dragEndEvt;
		}
		
//		Puzzle.scramble();
//		Puzzle.scramble();
		
		Puzzle.moves = 0;
		Puzzle.startTime = (new Date()).getTime();
		Puzzle.doTimer();
		
		Puzzle.started = true;
//		Puzzle.doTimer();
//		Puzzle.showTimeBar(false);
	},
	
	stop : function(cleanup)
	{
		window.clearTimeout(Puzzle.timerID);
		Puzzle.started = false;
		if (cleanup)
		{
			Puzzle.puzFrame.innerHTML ="";
			Puzzle.blks = [];
		}
		else
		{
			for (var i = 0; i < Puzzle.blks.length; i++)
			{
				var b = Puzzle.blks[i].blk;
				Drag.stop(b);
				b.onDragStart = new Function();
				b.onDragEnd = new Function();
				if (cleanup) Puzzle.puzFrame.removeChild(b);
			}
		}
		//if (cleanup) Puzzle.blks = [];
	},
	
	doTimer : function()
	{
		Puzzle.calcTime();
		Puzzle.timerID = window.setTimeout('Puzzle.doTimer()', 1000);
	},

calcTime : function()
{
	var currTime = (new Date()).getTime();
	var tm = currTime - Puzzle.startTime;
	Puzzle.onTime(tm);
	return tm;
},

contains : function(array, value)
{
	for (var i = 0; i < array.length; i++)
	{
		if (array[i] == value) return true;
	}
	return false;
},
	
scramble : function()
{
	var randoms = new Array(Puzzle.blks.length);
	for (var n = 0; n < Puzzle.blks.length; n++)
	{
		var value = Math.floor(Math.random() * Puzzle.blks.length);
		while (Puzzle.contains(randoms, value)) value = Math.floor(Math.random() * Puzzle.blks.length);
		randoms[n] = value;
	}

	for (var i = 0; i < Puzzle.blks.length; i++)
	{
		var b1 = Puzzle.blks[i];
		var b2 = Puzzle.blks[randoms[i]];
		Puzzle.swop(b1, b2);
	}
},
	
	change : function(sz)
	{
//		Puzzle.showTimeBar(true);
//		Puzzle.tempTimerID = window.setTimeout("Puzzle.realChange({w:" + sz.w + ",h:" + sz.h + "})", 50);

		Puzzle.stop(true);
//		for (var i = 0; i < Puzzle.blks.length; i++)
//		{
//			var b = Puzzle.blks[i];
//			Puzzle.puzFrame.removeChild(b.blk);
//		}
		//Puzzle.puzFrame.innerHTML ="";
		Puzzle.init(document.getElementById("puzzle"), Puzzle.img, sz);
//		Puzzle.showTimeBar(false);
	},
//	realChange : function(sz)
//	{
//		window.clearTimeout(Puzzle.tempTimerID);
//		Puzzle.stop();
//		Puzzle.puzFrame.innerHTML ="";
//		Puzzle.init(document.getElementById("puzzle"), Puzzle.img, sz);
//		Puzzle.showTimeBar(false);
//	},
	
	tempTimerID : 0,
	solve : function(restore)
	{
		if (!Puzzle.started) return;
		
		for (var i = 0; i < Puzzle.blks.length; i++)
		{
			var b = Puzzle.blks[i];
			b.blk.style.zIndex = b.i;
			setX(b.blk, Puzzle.blks[b.blk.i].x);
			setY(b.blk, Puzzle.blks[b.blk.i].y);
		}
		
		if (restore) { Puzzle.tempTimerID = window.setTimeout('Puzzle.restore()', 3000); }
	},

	restore : function()
	{
		window.clearTimeout(Puzzle.tempTimerID);
		for (var i = 0; i < Puzzle.blks.length; i++)
		{
			var b = Puzzle.blks[i];
			b.blk.style.zIndex = b.ci;
			setX(b.blk, Puzzle.blks[b.blk.ci].x);
			setY(b.blk, Puzzle.blks[b.blk.ci].y);
		}
	},
	
	onMove : null,
	onComplete : null,
	onTime : null
};

var Drag = {
obj : null,

init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
{
o.onmousedown = Drag.start;

o.hmode = bSwapHorzRef ? false : true ;
o.vmode = bSwapVertRef ? false : true ;

o.root = oRoot && oRoot !== null ? oRoot : o ;

if (o.hmode && isNaN(parseInt(o.root.style.left, 10))) {o.root.style.left = "0px";}
if (o.vmode && isNaN(parseInt(o.root.style.top, 10))) {o.root.style.top = "0px";}
if (!o.hmode && isNaN(parseInt(o.root.style.right, 10))) {o.root.style.right = "0px";}
if (!o.vmode && isNaN(parseInt(o.root.style.bottom, 10))) {o.root.style.bottom = "0px";}

o.minX = typeof minX != 'undefined' ? minX : null;
o.minY = typeof minY != 'undefined' ? minY : null;
o.maxX = typeof maxX != 'undefined' ? maxX : null;
o.maxY = typeof maxY != 'undefined' ? maxY : null;

o.xMapper = fXMapper ? fXMapper : null;
o.yMapper = fYMapper ? fYMapper : null;

o.root.onDragStart = new Function();
o.root.onDragEnd = new Function();
o.root.onDrag = new Function();
},

stop : function(o)
{
	o.onmousedown = new Function();
},

start : function(e)
{
var o = Drag.obj = this;
e = Drag.fixE(e);
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
o.root.onDragStart(x, y);

o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;

if (o.hmode) {
if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
} else {
if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
}

if (o.vmode) {
if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
} else {
if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
}

document.onmousemove = Drag.drag;
document.onmouseup = Drag.end;

return false;
},

drag : function(e)
{
e = Drag.fixE(e);
var o = Drag.obj;

var ey = e.clientY;
var ex = e.clientX;
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
var nx, ny;

if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

if (o.xMapper) nx = o.xMapper(y)
else if (o.yMapper) ny = o.yMapper(x)

Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;

Drag.obj.root.onDrag(nx, ny);
return false;
},

end : function()
{
document.onmousemove = null;
document.onmouseup = null;
Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
Drag.obj = null;
},

fixE : function(e)
{
if (typeof e == 'undefined') e = window.event;
if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;

return e;
}
};

function getStyle( elem, name ) {
if (elem.style[name])
return elem.style[name];
else if (elem.currentStyle)
return elem.currentStyle[name];
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/([A-Z])/g,"-$1");
name = name.toLowerCase();
var s = document.defaultView.getComputedStyle(elem,"");
return s && s.getPropertyValue(name);
} else
return null;
}
function getW(elem) {
return parseInt( getStyle( elem, "width" ) );
}
function getH(elem) {
return parseInt( getStyle( elem, "height" ) );
}
function setX(elem, pos) {
elem.style.left = pos + "px";
}
function setY(elem, pos) {
elem.style.top = pos + "px";
}

function GetTime(ms)
{
	var ss = Math.floor((ms)/1000);
	var mm = Math.floor(ss/60);
	ss = ss%60;
	var hh = Math.floor(mm/60);
	mm = mm%60;
	
	return (hh<10?'0':'') + hh.toString() + ':' + (mm<10?'0':'') + mm.toString() + ':' + (ss<10?'0':'') + ss.toString();
}

function EvalSound(soundobj) {
  var thissound=LocalGetElementById(soundobj);
  try
  {
		if (thissound) thissound.Play();
  }
  catch(Error) {/*alert("error playing sound " + Error.toString());*/}
}
