var width = 120;

window.onload = setupPuzzle;

//Make an array with all the possible positions for pieces
var point1 = {	left:0,			top:0}
var point2 = {	left:width,		top:0}
var point3 = {	left:width*2,	top:0}
var point4 = {	left:width*3,	top:0}
var point5 = {	left:0,			top:width}
var point6 = {	left:width,		top:width}
var point7 = {	left:width*2, 	top:width}
var point8 = {	left:width*3, 	top:width}
var point9 = {	left:0,			top:width*2}
var point10 = {	left:width,		top:width*2}
var point11 = {	left:width*2,	top:width*2}
var point12 = {	left:width*3,	top:width*2}
var point13 = {	left:0,			top:width*3}
var point14 = {	left:width,		top:width*3}
var point15 = {	left:width*2,	top:width*3}
var point16 = {	left:width*3,	top:width*3}

var points = new Array(point1, point2, point3, point4, point5, point6, point7, point8, point9, point10, point11, point12, point13, point14, point15, point16);

//Store the pieces in memory, and a reference to which position is blank
var blankPoint;
var pieces = new Array;

var startTime;
var endTime;

//create the puzzle and jumble it up
function setupPuzzle() {
	//load up the final background image
	preload = document.createElement('img');
	preload.src = 'win-bg.png';
	
	//
	wrap = document.createElement('div');
	wrap.id = 'puzzle-wrap';
	wrap.style.opacity = 0;
	
	//build the timer
	timer = document.createElement('p');
	timer.id = 'timer';
	timer.innerHTML = '&nbsp;';
	wrap.appendChild(timer);
	
	background = document.createElement('div');
	background.id = 'puzzle-bg';
	background.style.opacity = 1;
	wrap.appendChild(background);
	puz = document.createElement('div');
	puz.id = 'puzzle';
	background.appendChild(puz)
	for (var i = 1;i < 16;i++) {
		piece = document.createElement('div');
		piece.setAttribute('class','piece');
		piece.id = 'piece-'+i;
		
		piece.style.backgroundImage = 'url(images/'+piece.id+".png)";
		piece.style.left = points[i-1].left+"px";
		piece.style.top = points[i-1].top+"px";
		
		puz.appendChild(piece);
	}
	document.getElementById('wrap').appendChild(wrap);
	fadeElement('puzzle-wrap',1,false);
	var objects = document.getElementsByClassName('piece');
	
	
	
	//a new order for the array
	pieces = randomise(objects);
	while (!checkSolvable()) {
		pieces = randomise(objects);
	}
	
	setTimeout('positionPieces()',1500);
	
}

function positionPieces() {
	for (var i = 0;i < pieces.length;i++) {
		var piece = pieces[i];
		if (piece != "blank") {
			slidePiece(piece.id,points[i]),
			piece.setAttribute('onclick',"movePiece("+i+")");
			//piece.style.left = points[i].left+"px";
			//piece.style.top = points[i].top+"px";
		} else {
			blankPoint = i;
		}
	}
}

function hint() {
	for (var i = 1;i < pieces.length;i++) {
		var piece = document.getElementById();
		slidePiece('piece-'+i,points[i-1]);
	}
	setTimeout('positionPieces()',2000);
}


function randomise(array) {
	var newArray = new Array;
	var blankExists = false;
	for (var i = 0;i < array.length;i++) {
		newArray[i] = array[i];
		if (array[i] == 'blank') {
			blankExists = true;
		}
	}
	
	for (var i = 0;i<newArray.length;i++) {
		var rand = Math.floor(Math.random()*newArray.length)
		var temp = newArray[rand];
		newArray[rand] = newArray[i];
		newArray[i] = temp;
	}
	if (!blankExists) {
		var temp = newArray[rand];
		newArray[rand] = "blank";
		newArray[newArray.length] = temp;
	}
	return newArray;
}

function checkSolvable() {
	//Solvability algorithm from http://www.cs.bham.ac.uk/~mdr/teaching/modules04/java2/TilesSolvability.html
	//we need the number of inversions and the location of the blank piece
	var inversions = 0;
	var blank = 0;
	for (var i=0;i<pieces.length; i++) {
		var piece = pieces[i];
		if (piece != 'blank') {
			//get the number of the piece from the ID
			var pieceNo = parseInt(piece.id.split('-')[1]);
			//check following pieces for inversions
			for (var j=i+1;j<pieces.length;j++) {
				if (pieces[j] != 'blank') {
					var nextPiece = pieces[j].id.split('-')[1];
					var nextPiece = parseInt(nextPiece);
					//an invesrion occurs when a piece has a lower number than the proceeding piece
					if (pieceNo > nextPiece) {
						inversions++;
					}
				}
			}
		}
		else {
			//blank location
			blank = i;
		}
	}
	inversionsOdd = inversions %2;
	blankRow = (4-(Math.floor(blank/4)));
	blankOdd = blankRow %2;
	//A solvable puzzle has eitheran even number of inversions and  
	//the blank spot an even number of rows from the bottom, or an odd
	//number of inversions and the blank an even number of rows from the bottom
	if ((!inversionsOdd && blankOdd) || (inversionsOdd && !blankOdd)) {
		return true;
	}
	else {
		return false;
	}
	
}

function movePiece(piece) {
	if (!startTime) {
		startTime = new Date().getTime()
		updateTimer()
	}
	row = Math.floor(piece/4);
	col = piece % 4;
	blankRow = Math.floor(blankPoint/4);
	blankCol = blankPoint % 4;
	if ((row == blankRow) || (col == blankCol)) {
		if (row == blankRow) {
			if (blankPoint > (piece+1)) {
				movePiece(piece+1);
			}
			if (blankPoint < (piece-1)) {
				movePiece(piece-1);
			}
		}
		if (col == blankCol) {
			if (blankPoint > (piece+4)) {
				movePiece(piece+4);
			}
			if (blankPoint < (piece-4)) {
				movePiece(piece-4);
			}
		}
		thePiece = pieces[piece];
		slidePiece(thePiece.id,points[blankPoint])
/*
		thePiece.style.left = points[blankPoint].left+"px";
		thePiece.style.top = points[blankPoint].top+"px";
*/
		
		thePiece.setAttribute('onclick',"movePiece("+blankPoint+")");
		pieces[blankPoint] = thePiece;
		pieces[piece] = "blank";
		blankPoint = piece;
	}
	checkFinished();
}

function slidePiece(id,point) {
	var piece = document.getElementById(id)
	var currentLeft = parseFloat(piece.style.left.replace("px",""))
	var currentTop = parseFloat(piece.style.top.replace("px",""))
	if (piece) {
		if (currentLeft < point.left) {
			var diff = point.left - currentLeft;
			if (diff < 1) {
				piece.style.left = point.left+"px";
			} else {
				var newLeft = currentLeft+15;
				piece.style.left = newLeft+"px";
				setTimeout(function(){ slidePiece(piece.id,point) },10); 
			}
		}
		if (currentLeft > point.left) {
			var diff = currentLeft - point.left;
			if (diff < 1) {
				piece.style.left = point.left+"px";
			} else {
				var newLeft = currentLeft-15;
				piece.style.left = newLeft+"px";
				setTimeout(function(){ slidePiece(piece.id,point) },10); 
			}
		}
		if (currentTop < point.top) {
			var diff = point.top - currentTop
			if (diff < 1) {
				piece.style.top = point.top+"px";
			} else {
				var newTop = currentTop+15;
				piece.style.top = newTop+"px";
				setTimeout(function(){ slidePiece(piece.id,point) },10); 
			}
		}
		if (currentTop > point.top) {
			var diff = currentTop - point.top;
			if (diff < 1) {
				piece.style.top = point.top+"px";
			} else {
				var newTop = currentTop-15;
				piece.style.top = newTop+"px";
				setTimeout(function(){ slidePiece(piece.id,point) },10); 
			}
		}
	}
}

var timerRunning = true;
function updateTimer() {
	if (timerRunning) {
		timer = document.getElementById('timer');
		now = new Date().getTime();
		timeElapsed = now-startTime;
		minutes = Math.floor((timeElapsed/1000)/60);
		timeElapsed -= minutes*60000;
		seconds = Math.floor(timeElapsed/1000);
		timeElapsed -= seconds*1000;
		hundredths = Math.floor(timeElapsed/10);
		timerString = "";
		if (minutes < 10) {
			timerString += "0"+minutes;
		}
		else timerString += minutes;
		timerString += ":";
		if (seconds < 10) {
			timerString += "0"+seconds;
		}
		else timerString += seconds;
		timerString += ":";
		if (hundredths < 10) {
			timerString += "0"+hundredths;
		}
		else timerString += hundredths;
		timer.innerHTML = timerString;
		setTimeout('updateTimer()',10);
	}
}

function checkFinished() {
	var count = 0;
	for (var i=0;i<pieces.length;i++) {
		piece = pieces[i];
		if (piece != 'blank') {
			if (piece.id != 'piece-'+(i+1)) {
				break;
			}
			else {
				count++;
			}
		}
	}
	if (count == 15) {
		timerRunning = false;
		endTime = new Date().getTime();
		setTimeout('endGame()',1000);
	}
}

function createXMLHttpRequest() {
   try { return new XMLHttpRequest(); } catch(e) {}
   try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
   alert("XMLHttpRequest not supported");
   return null;
}
/*

function logScore(name,twitter) {
	params = "name="+name+"&twitter="+twitter+"&score="+(Math.floor((endTime-startTime)/10));
	xhr = createXMLHttpRequest();
	xhr.open('POST','http://sshrpe.me.uk/save-score.php')
	xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xhr.setRequestHeader("Content-length", params.length);
	xhr.setRequestHeader("Connection", "close");
	xhr.onreadystatechange = function() {
		if(xhr.readyState == 4 && xhr.status == 200) {
			
		}
	}
	xhr.send(params);

}
*/
function endGame() {
	var winBG = document.createElement('div');
	winBG.id = 'win-bg';
	winBG.style.opacity = 0;
	var wrap = document.getElementById('puzzle-wrap');
	wrap.appendChild(winBG);
	fadeElement('puzzle-bg',5,true);
	fadeElement('win-bg',5,false);
	//setTimeout(function() { window.location = 'http://stuartsharpe.co.uk'},3000);
}

function fadeElement(id, time, out) {
	var element = document.getElementById(id);
	var currentOpacity = parseFloat(element.style.opacity)
	if (element) {
		if (out) {
			if (currentOpacity > 0) {
				var newOpacity = currentOpacity-(1/(time*10))
				element.style.opacity = newOpacity;
				setTimeout('fadeElement("'+id+'",'+time+',true)',10); 
			}
		}
		else {
			if (currentOpacity < 1) {
				var newOpacity = currentOpacity+(1/(time*10))
				element.style.opacity = newOpacity;
				setTimeout('fadeElement("'+id+'",'+time+',false)',10); 
			}
		}
	}
}