



//initialise the docking boxes manager
var manager = new dbxManager(
	'photoswap',			// session ID [/-_a-zA-Z0-9/]
	'yes',					// enable box-ID based dynamic groups ['yes'|'no']
	'yes',					// hide source box while dragging ['yes'|'no']
	'link'					// toggle button element type ['link'|'button']
	);


//create new docking boxes group
var group = new dbxGroup(
	'photo', 				// container ID [/-_a-zA-Z0-9/]
	'freeform', 			// orientation ['vertical'|'horizontal'|'freeform'|'freeform-insert'|'confirm'|'confirm-insert']
	'7', 					// drag threshold ['n' pixels]
	'yes',					// restrict drag movement to container/axis ['yes'|'no']
	'15', 					// animate re-ordering [frames per transition, or '0' for no effect]
	'no', 					// include open/close toggle buttons ['yes'|'no']
	'',		 				// default state ['open'|'closed']

	'', 										// word for "open", as in "open this box"
	'', 										// word for "close", as in "close this box"
	'click-down and drag to move this piece', 	// sentence for "move this box" by mouse
	'', 										// pattern-match sentence for "(open|close) this box" by mouse
	'use the arrow keys to move this piece',	// sentence for "move this box" by keyboard
	'',  										// pattern-match sentence-fragment for "(open|close) this box" by keyboard
	'%mytitle%  [%dbxtitle%]',					// pattern-match syntax for title-attribute conflicts

	'',											// confirm dialog sentence for "selection okay"
	''											// confirm dialog sentence for "selection not okay"
	);




//use the rules engine to prevent diagonal movement
group.setRule('NESW');





//get the collection of box elements, which in this case is all DIVs inside the group
//to use for changing the background so we can change the picture picture around
var boxes = group.container.getElementsByTagName('div');

//create an array of the pieces in order to reset with
//and create an empty array for shuffling the pieces
//which we'll populate on demand each time
var shuffling = [], resetting = [];
for(var i=0; i<20; i++)
{
	resetting.push('P' + i);
}

//create a busy flag to prevent reset and shuffle happening at the same time
var busy = false;

//create a variable to store the ID of the primary box of each reset insert action
var primaryID = null;






//use onboxdrag to record the primary box of each insertion action
//and to hide the success message in response to any movement
//(this will catch shuffle and restore, as well as manual actions)
manager.onboxdrag = function()
{
	//record the primary box ID
	primaryID = this.getID(this.sourcebox);
	
	//hide the success message
	document.getElementById('congratulations').style.display = 'none';
	return true;
};





//reset function uses insert() to place the pieces in order
//by moving each piece to the end of the group
//we use the primary box ID reference we saved from onboxdrag
//so that we only handle the onafteranimate of that one
//because it will fire for all the ones that get displaced as well
function reset()
{
	//if the busy flag is true ignore this action
	if(busy) { return; }
	
	//set the busy flag
	busy = true;
	
	//reset the piece pointer 
	var pointer = 0;
	
	//if the reset occurs with animation then firefox stops after a few pieces 
	//for no explicable reason ... the code is fine, every other browser is fine, 
	//firefox is just being stupid; so set it 0 to temporarily disable it
	group.resolution = 1;
	
	//create an onafteranimate handler
	manager.onafteranimate = function()
	{
		//if this is the primary box
		if(primaryID == this.getID(this.sourcebox))
		{
			//increase the piece pointer
			pointer ++;
			
			//if there are more pieces to move
			if(pointer < resetting.length)
			{
				//insert the next piece at the end of the group
				group.insert(resetting[pointer], false);
			}
			
			//otherwise we're done
			else
			{
				//clear the busy flag
				busy = false;
				
				//and restore the animation resolution
				group.resolution = 15;
			}
		}
	}

	//insert the first piece at the end of the group
	group.insert(resetting[pointer], false);
}






//shuffle function randomly moves the pieces around and works in a similar way to reset
//but the special situation here is where we have to handle a swap operation that fails
//which it can do under a few different circumstances
//(for more info see: http://www.brothercake.com/site/resources/scripts/dbx/setup6/)
function shuffle()
{
	//if the busy flag is true ignore this action
	if(busy) { return; }
	
	//set the busy flag
	busy = true;
	
	//reset the piece pointe
	var pointer = 0;
	
	//create an onafteranimate handler
	manager.onafteranimate = function()
	{
		//if this is the primary box
		if(primaryID == this.getID(this.sourcebox))
		{
			//increase the piece pointer
			pointer += 2;
			
			//if there are more pieces to move
			if(pointer < shuffling.length)
			{
				//try to swap the next two pieces, and while it fails just increase the pointer and try again
				//clear the busy flag in case this happens at the end of a shuffle routine
				//if we reach the pointer's limit then just abandon this shuffle
				while(!(group.swap(shuffling[pointer], shuffling[pointer + 1], false)))
				{
					busy = false;
					pointer += 2;
					if(pointer >= shuffling.length)
					{
						break;
					}
				}
			}
			
			//otherwise we're done
			else
			{
				//clear the busy flag
				busy = false;
			}
		}
	}

	//try to swap the first two pieces, and while it fails just increase the pointer and try again
	//clear the busy flag in case this happens at the end of a shuffle routine
	//if we reach the pointer's limit then just abandon this shuffle
	while(!(group.swap(shuffling[pointer], shuffling[pointer + 1], false)))
	{
		busy = false;
		pointer += 2;
		if(pointer >= shuffling.length)
		{
			break;
		}
	}
}





//store the previous state before each swap
//so that we don't congratulate for picking the first piece up
//and then immediately putting it down again!
var laststate = '';

//create an onstatechange function to detect when the picture is complete
manager.onstatechange = function()
{
	//save the state string and remove the name part
	//then strip it of the "+" symbols we don't need
	var state = this.state.split('=')[1].replace(/\+/g, '');

	//if the laststate is empty, save it to laststate immediately
	if(laststate == '') { laststate = state; }

	//hide the success message
	document.getElementById('congratulations').style.display = 'none';

	//if the state is correct, then the string
	//will be the same as the resetting array when joined
	if(state == resetting.join())
	{
		//so show the success message, but not if the busy flag is true
		//(otherwise we'll be congratulating pressing the "reset" button!)
		//and also not if the state is the same as the last state
		//(so you don't get it just by picking up and dropping the first image)
		if(!busy && state != laststate)
		{
			document.getElementById('congratulations').style.display = 'block';
		}
	}

	//save the state to last state
	laststate = state;

	//don't save the cookie state
	return false;
};











//control form scripting
var frm = document.getElementById('controls');
if(frm)
{
	//submit event is for shuffling the picture
	frm.onsubmit = function()
	{
		//populate the shuffling array randomly
		//add 30 pairs not just 20 so we get a good old shuffle
		shuffling = [];
		for(var i=0; i<30; i++)
		{
			for(var j=0; j<2; j++)
			{
				shuffling.push('P' + (1 + Math.floor(Math.random() * (20))));
			}
		}

		//run the shuffle function with the shuffled array
		shuffle();

		//don't perform default action
		return false;
	};

	//reset event is for resetting the picture
	frm.onreset = function()
	{
		//run the reset function with the sorted array
		reset();

		//don't perform default action
		return false;
	};

	//select element change event is for changing the picture
	frm['pic'].onchange = function()
	{
		//get the image path
		var img = 'images/puzzle/' + this.options[this.options.selectedIndex].value + '.jpg';

		//iterate through the boxes and apply this as a background image
		for(var i=0; i<boxes.length; i++)
		{
			boxes[i].style.backgroundImage = 'url(' + img + ')';
		}
	};
}




