﻿// JScript File

var dbg;
function debug(str)
{
    return;
	if(!dbg) dbg = document.getElementById("debug");
	if(typeof(str) == "object")
	{
	
		var props = "";
		for(var p in str)
			props += p + " = " + str[p] + "; ";
		str = props;
	}
	dbg.innerHTML += "<br/>" + str;
}

/////////////////////////////////

function fixEvent(e)
{
	//fix event properties
	if (!e) var e = window.event;
	if (e.pageX == null && e.clientX != null) 	
	{
		e.pageX = e.clientX + document.body.scrollLeft
			+ document.documentElement.scrollLeft;
		e.pageY = e.clientY + document.body.scrollTop
			+ document.documentElement.scrollTop;
	}
	if(e.which == null)
	{
		if(e.button == 1)
			e.which = 1;
		else if(e.button == 4)
			e.which = 2;
		else if(e.button == 2)
			e.which = 3;
	}
	return e;
}

function getWindowInfo()
{
	var myWidth = 0, myHeight = 0;
	if( typeof( window.innerWidth ) == 'number' ) {
		//Non-IE
		myWidth = window.innerWidth;
		myHeight = window.innerHeight;
	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//IE 6+ in 'standards compliant mode'
		myWidth = document.documentElement.clientWidth;
		myHeight = document.documentElement.clientHeight;
	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		//IE 4 compatible
		myWidth = document.body.clientWidth;
		myHeight = document.body.clientHeight;
	}

	var scrOfX = 0, scrOfY = 0;
	if( typeof( window.pageYOffset ) == 'number' ) {
		//Netscape compliant
		scrOfY = window.pageYOffset;
		scrOfX = window.pageXOffset;
	} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		//DOM compliant
		scrOfY = document.body.scrollTop;
		scrOfX = document.body.scrollLeft;
	} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		//IE6 standards compliant mode
		scrOfY = document.documentElement.scrollTop;
		scrOfX = document.documentElement.scrollLeft;
	}
	return {width: myWidth, height: myHeight, scrollY: scrOfY, scrollX: scrOfX};
}

var puzzleItems;// = new Array();
var mainLayer;
var selectionLayer;
var topLayer;
var hoverCell;
var partsX = 8;
var partsY = 8;

var selectedItems = new Array();
var mouseDown = false;
var clearSelectionOnMouseUp = false;
var mouseDownPageX;
var mouseDownPageY;

var topMargin = 20;
var offsetY = 0;

//create grid
var grid = {
	sizeX: 100,
	sizeY: 80,
	cols: 1000,
	map: new Array(),
	key: function(event) 
	{
		return parseInt(event.pageY/this.sizeY) * this.cols + parseInt(event.pageX/this.sizeX);
	},
	position: function(event)
	{
		return { top: parseInt(event.pageY/this.sizeY)*this.sizeY, left: parseInt(event.pageX/this.sizeX)*this.sizeX };
	},
	setAt: function(event, pc) 
	{
		var key = this.key(event);
		if(pc != null)
		{		
			pc.key = key;		
			pc.gridX = parseInt(event.pageX/this.sizeX);
			pc.gridY = parseInt(event.pageY/this.sizeY);
			pc.pageX = pc.gridX * this.sizeX;
			pc.pageY = pc.gridY * this.sizeY;
			pc.dragElement.style.left = pc.pageX+"px";
			pc.dragElement.style.top = pc.pageY+"px";			
		}
		this.map[key] = pc;
	},
	getAt: function(event) 
	{
		var key = this.key(event);
		return this.map[key];
	},
	clear: function()
	{
		this.map = new Array();
	}
}
//create puzzle puzzleItems
function createPuzzle(img)
{
	mainLayer = document.getElementById("mainLayer");
	selectionLayer = document.getElementById("selectionLayer");
	topLayer = document.getElementById("topLayer");
	hoverCell = document.getElementById("hoverCell");
	
	puzzleItems = new Array();

	iw = img.width;
	ih = img.height;
	
	
	
	ew = parseInt(iw/partsX);
	eh = parseInt(ih/partsY);
	
	ew2 = parseInt(ew/2);
	eh2 = parseInt(eh/2);
	
	grid.sizeX = ew2;
	grid.sizeY = eh2;
	
	
	hoverCell.style.width = ew2+"px";
	hoverCell.style.height = eh2+"px";
	
	debug("grid: " + ew2 + ", " + eh2);
	
	var dx = ew2;
	var dy = parseInt((offsetY + eh2) / eh2)*eh2;
	//alert(canvasOffset.top);
	
	//IE png fix
	var arVersion = navigator.appVersion.split("MSIE");
	var version = parseFloat(arVersion[1]);
	
	debug(version);
	
	//create puzzle elements
	var items = new Array();	
	
	for(var i=0; i<partsY; i++)
	{	
		for(var j=0; j<partsX; j++)
		{
			var elem = document.createElement("div");
			var elemClip = document.createElement("div");
			var elemIcon = document.createElement("div");
			var elemImg;
			
			
			//IE png fix
			if ((version < 7 && version >= 5.5) && (document.body.filters)) 
			{						
				elemImg = document.createElement("span");								
				elemImg.style.width = iw + "px";
				elemImg.style.height = ih + "px";
				elemImg.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'" + 
					img.src + 
					"\', sizingMethod='scale')";				
			}
			else
			{
				elemImg = document.createElement("img");
				elemImg.src = img.src;
			}			
			
			var item = new Object();
			item.dragElement = elem;
			item.x = j;
			item.y = i;			
			
			item.id = puzzleItems.length;
			puzzleItems.push(item);
			
			elem.className = "puz";
			//elem.style.left = ew2*j+"px";
			//elem.style.top = eh2*i+"px";
			elem.style.width = ew2+"px";
			elem.style.height = eh2+"px";
			
			
			//debug((canvasOffset.left + ew2*j) + ", " + (canvasOffset.top + eh2*i));
					
			
			elemClip.style.left = -ew/4+"px";
			elemClip.style.top = -eh/4+"px";
			elemClip.style.width = ew+"px";
			elemClip.style.height = eh+"px";
										
			elemImg.style.left = -ew*j+"px";
			elemImg.style.top = -eh*i+"px";			
						
			elemClip.appendChild(elemImg);
			elem.appendChild(elemClip);

			//icon
			elemIcon.className = "icon";
			elemIcon.style.zIndex = 2;
			elemIcon.style.top = 0+"px";
			elemIcon.style.left = 0+"px";
			elemIcon.style.width = ew2-2+"px";
			elemIcon.style.height = eh2-2+"px";
			
			elem.appendChild(elemIcon);
			
			item.ord = Math.random();
			items.push(item);
		}
	}

    //randomize
	items.sort(function(x,y){return x.ord-y.ord;});
	
	mainLayer.style.height = offsetY + topMargin + partsY * eh + "px";
	
	//place on screen
	var cols = Math.floor(partsX/2);
	for(var i=0; i<items.length; i++)
	{		
		var item = items[i];
		var itemY = Math.floor(i/cols);
		var itemX = i-itemY*cols;
		
		var event = {pageX: itemX*ew2*2 + (itemY%2+1)*ew2, pageY: dy + itemY*eh2};	
		grid.setAt(event, item);
				
		mainLayer.appendChild(item.dragElement);	
	}
	
	/*
	var ox = getWindowInfo().width / 2 - (partsX * ew2);
	//alert(ox);
	for(var i=0; i<partsY; i++)
	{	
		for(var j=0; j<partsX; j++)
		{			
			var index = i * partsX + j;			
			var item = items[index];
			
			var event = {pageX: ox + 2*ew2*j, pageY: dy + 2*eh2*i};	
			grid.setAt(event, item);
				
			mainLayer.appendChild(item.dragElement);
		}
	}
	*/
	//attach mouse events
	attachEvents();
}


function selectItem(item, force)
{
	//select item and its neighbours
	if(!force && selectedItems[item.id] != null)
		return;
	var stack = new Array();
	var checked = new Array();
	stack.push(item);
	var center,left,right,up,down;
	while(stack.length > 0)
	{
		center = stack.pop();		
		if(checked[center.id])
			continue;
			
		selectedItems[center.id] = center;			
		

		checked[center.id] = true;
		left = grid.map[center.gridY * grid.cols + center.gridX - 1];
		right = grid.map[center.gridY * grid.cols + center.gridX + 1];
		up = grid.map[(center.gridY - 1) * grid.cols + center.gridX];
		down = grid.map[(center.gridY + 1) * grid.cols + center.gridX];

		if(left && left.x == center.x-1 && left.y == center.y)
		{
			if(checked[left.id] == null)
				stack.push(left);			
		}
		if(right && right.x == center.x+1 && right.y == center.y)
		{
			if(checked[right.id] == null)						
				stack.push(right);			
		}
		if(up && up.x == center.x && up.y == center.y-1)
		{
			if(checked[up.id] == null)			
				stack.push(up);			
		}
		if(down && down.x == center.x && down.y == center.y+1)
		{
			if(checked[down.id] == null)
				stack.push(down);			
		}
	}	 
}

function dettachSelectedItems()
{
	//dettach
	for(var id in selectedItems)
	{
		var item = selectedItems[id];
		mainLayer.removeChild(item.dragElement);
		selectionLayer.appendChild(item.dragElement);
		grid.map[item.key] = null;
	}
	onItemsSelect();
}

function onItemsSelect()
{
	for(var id in selectedItems)
	{
		var item = selectedItems[id];
		item.dragElement.className = "puz selected";
	}
}


function onItemsDeselect()
{
	for(var id in selectedItems)
	{
		var item = selectedItems[id];
		item.dragElement.className = "puz";
	}
}

//drag&drop
function mousedown(event) 
{
	clearSelectionOnMouseUp = false;
	var event = fixEvent(event);

	if(event.which != 1)
		return;	  
	if(event.pageY < offsetY - topMargin)
	{	
		//alert('up');
		return;
	}
	
	var wi = getWindowInfo();
		debug(wi);
	if(	event.pageX > wi.width + wi.scrollX - 20 ||
		event.pageY > wi.height + wi.scrollY - 20)
		return false;
	
	//initialize dragging
	selectionLayer.style.left = 0+"px";
	selectionLayer.style.top = 0+"px";
			
	mouseDown = true;
	mouseDownPageX = event.pageX;
	mouseDownPageY = event.pageY;

	//update selection
	var item = grid.getAt(event);
	if(item != null)
	{	  
		hoverCell.style.width = grid.sizeX+"px";
		hoverCell.style.height = grid.sizeY+"px";
		hoverCell.style.borderColor = "#fa4904";//red
		
		if(selectedItems[item.id] != null)
		{
			//item is in selection
			for(var id in selectedItems)
			{
				//include neigbours
				selectItem(selectedItems[id], true);
			}
			dettachSelectedItems();
			return false;
		}
		else
		{
			onItemsDeselect();
			clearSelectionOnMouseUp = true;
			selectedItems = new Array();			
			selectItem(item);
			dettachSelectedItems();			
			return false;
		}
	}
	else
	{	
		onItemsDeselect();
		selectedItems = new Array();		
		//drag rectangle
		hoverCell.style.width = 0;
		hoverCell.style.height = 0;
		hoverCell.style.borderColor = "blue";
		hoverCell.style.top = event.pageY+"px";
		hoverCell.style.left = event.pageX+"px";
		hoverCell.style.visibility = "visible";		
		
		return false;
	}
};

function mousemove(event) 
{
	var event = fixEvent(event);
	if(mouseDown)
	{
		if(event.pageY < offsetY)
			return;
		var pos = grid.position(event);
		if(pos.top < offsetY)
			return;
	
		if(selectedItems.length > 0)
		{
			var x,y;
			x = event.pageX - mouseDownPageX;
			y = event.pageY - mouseDownPageY;
				
			selectionLayer.style.left = x+"px";
			selectionLayer.style.top = y+"px";	

			var pos = grid.position(event);
			
			hoverCell.style.top = pos.top+"px";
			hoverCell.style.left = pos.left+"px";
			hoverCell.style.visibility = "visible";
			
			return false;
		}
		else
		{	
			hoverCell.style.left = Math.min(event.pageX, mouseDownPageX)+"px";		
			hoverCell.style.top = Math.min(event.pageY, mouseDownPageY)+"px";			
			hoverCell.style.width = Math.abs(event.pageX - mouseDownPageX)+"px";
			hoverCell.style.height = Math.abs(event.pageY - mouseDownPageY)+"px";			
			return false;
		}		
	}
};

function mouseup(event) 
{
	var event = fixEvent(event);
	if(mouseDown)
	{
		mouseDown = false;
		hoverCell.style.visibility = "hidden";
		
		if(selectedItems.length > 0)
		{
			var i,item,x,y;
			var mdpos = grid.position({pageX: mouseDownPageX, pageY: mouseDownPageY});
			var pos = grid.position(event);
			var dx = pos.left - mdpos.left;
			var dy = pos.top - mdpos.top;
						
			selectionLayer.style.left = dx+"px";
			selectionLayer.style.top = dy+"px";	

			//check new places
			var error = false;
			if(event.pageY < offsetY)
			{
				error = true;
			}
			else
			{
				for(var id in selectedItems)
				{
					item = selectedItems[id];
					x = item.pageX + dx;
					y = item.pageY + dy;
					
					if(x < 0 || y < offsetY || grid.getAt({pageX: x, pageY: y}))
					{
						error = true;
						break;
					}
				}
			}
			
			if(error)
			{
				for(var id in selectedItems)
				{
					item = selectedItems[id];
					selectionLayer.removeChild(item.dragElement);					
					grid.setAt({pageX: item.pageX, pageY: item.pageY}, item);
					mainLayer.appendChild(item.dragElement);	
				}
			}
			else
			{
				for(var id in selectedItems)
				{
					item = selectedItems[id];
					
					selectionLayer.removeChild(item.dragElement);
					
					x = item.pageX + dx;
					y = item.pageY + dy;
					//item.dragElement.style.left = x+"px";
					//item.dragElement.style.top = y+"px";	

					grid.setAt({pageX: x, pageY: y}, item);
					
					mainLayer.appendChild(item.dragElement);										
				}	
			}
			selectionLayer.style.left = 0+"px";
			selectionLayer.style.top = 0+"px";		
			
			if(clearSelectionOnMouseUp)
			{
				onItemsDeselect();
				selectedItems = new Array();
			}
			return false;
		}
		else
		{
			//select under drag rectangle	
			var minX = Math.min(mouseDownPageX, event.pageX);
			var maxX = Math.max(mouseDownPageX, event.pageX);
			var minY = Math.min(mouseDownPageY, event.pageY);
			var maxY = Math.max(mouseDownPageY, event.pageY);
			
			if(maxX-minX < grid.sizeX && maxY-minY < grid.sizeY)
				return true;
			var x1,x2,y1,y2;
			
			for(var i=0; i<puzzleItems.length; i++)
			{
				var item = puzzleItems[i];
				x1 = item.pageX;
				x2 = item.pageX + grid.sizeX;
				y1 = item.pageY;
				y2 = item.pageY + grid.sizeY;
				
				if( ((x1 <= maxX && x1 >= minX) || (minX <= x2 && minX >= x1)) &&
					((y1 <= maxY && y1 >= minY) || (minY <= y2 && minY >= y1)))
				{
					//selectedItems[item.id] = item;
					selectItem(item);
				}
			}
			
			if(selectedItems.length > 0)
			{				
				onItemsSelect();
				return false;
			}
		}		
	}
}

var puzzleCreated = function(){}

function initialize(imageSrc, parts)
{
    offsetY = document.getElementById("header").offsetHeight + topMargin;
    //alert(offsetY);
    partsX = parts;
    partsY = parts;
    //load image
    img = new Image();
    img.onload = function()
	{ 
		createPuzzle(this);
		puzzleCreated();
	};
    img.src = imageSrc;
}

function clearPuzzle()
{
	grid.clear();
	if(mainLayer)
		clearNode(mainLayer);
	if(hoverCell)
		hoverCell.style.visibility = "hidden";
}

function clearNode(node)
{
	if ( node.hasChildNodes() )
	{
		while ( node.childNodes.length >= 1 )
		{
			node.removeChild( node.firstChild );       
		} 
	}
}

function attachEvents()
{
    //attach event
    if (window.ActiveXObject)
    {
	    //IE
	    var ieButtonPressed = 0;	
	    document.onmousedown = function()
	    {
		    var event = window.event;
		    ieButtonPressed = event.button;
		    return mousedown(event);
	    }
	    document.onmousemove = function ()
	    {
		    var event = window.event;
		    if (ieButtonPressed != 0 && event.button == 0)
		    {
			    mouseup(event);
			    return false;
		    }
		    return mousemove(event);
	    }
	    document.onmouseup = function()
	    {
		    ieButtonPressed = 0;
		    return mouseup(window.event);
	    }
    }
    else
    {
	    document.onmousedown = mousedown;
	    document.onmousemove = mousemove;
	    document.onmouseup = mouseup;
    }
}
