// Trigered when mouse button is clicked, sets properties of container div based on selected slot
function selectSlot(evnt) {
	evt = (document.all) ? window.event : evnt;
	
  if (buffer != null) { 
    return; 
  }

	if (isScrolling) {
		return false;
	}
	
	isDown = true;
	
	document.ondblclick = new Function("return false");
	document.onmousewheel 	= new Function("return false");
	
	if (document.all) {
		// Browser is IE
		if (evt.button > 1) {
			// User is trying to use buttons (or wheel) other than the left
			return false;
		}
	} else {
		// Mozilla
		if (evt.button > 0) {
			// User is trying to use buttons (or wheel) other than the left
			return false;
		}
	}

	// Default times user has clicked on slot (used to prevent double clicks)
	clickNum = 1;
	
	// Store slot coords at time of mousedown
	slotLeft 	= this.parentNode.offsetLeft + 2;
	slotRight	= slotLeft + this.parentNode.offsetWidth;
	slotTop 	= this.parentNode.offsetTop + 2;

	idData 		= this.id.match(/([A-Za-z]{1,})(\d+)/, '');
	buffer = new Array();
	
	buffer['form'] = slotDataStr[dd_page][idData[1]][idData[2]]['form'];
	buffer['cell'] = slotDataStr[dd_page][idData[1]][idData[2]]['cell'];

  
	slotDataStr[dd_page][idData[1]][idData[2]]['form'] = '';
	slotDataStr[dd_page][idData[1]][idData[2]]['cell'] = '';


	// Set properties for the container slot
	containerObj.onmouseup 	= releaseSlot;
	containerObj.innerHTML 	= buffer['cell'];
	containerObj.style.left = slotLeft;
	containerObj.style.top 	= slotTop;
	containerObj.style.zIndex = 100;
	containerObj.style.width = (document.all) ? this.offsetWidth : this.offsetWidth-6;
	containerObj.style.height = (document.all) ? this.offsetHeight : this.offsetHeight-6;
	
	containerObj.style.visibility = 'visible';
	containerWidth = containerObj.offsetWidth;
	
	// Set properties for the selected slot
	this.onmouseup 	= releaseSlot;
	this.innerHTML 				= slotDataStr[dd_page][idData[1]][idData[2]]['cell'];
	this.style.backgroundColor 	= emptyBackgroundColor;
	this.style.borderColor 		= targetBorderColor;
	this.style.zIndex 			= 0;
		
	// Set start coord refrence variables
	downMouseX 			= evt.clientX;
	downMouseY 			= evt.clientY;
	var slotObjWidth 	= this.offsetWidth;
	var posX 			= slotLeft + evt.clientX - downMouseX;
	var posY 			= slotTop + evt.clientY - downMouseY;
	vertPad				= checkVerticalScroll(idData[1], idData[2]);
	
	slotObjCentr 		= slotObjWidth/2;
	var slotCtrX 		= posX + slotObjCentr;

	// Declair variable later used to store side of last known mouse move event
	retainSide			= (slotCtrX < centr) ? 'L' : 'R';
	// Declair variable later used to store slot of last known mouse move event
	retainSlot			= idData[2];
	selectedSlotNum		= idData[2];
	// Declare selected slot number that container is over
	currentSlotNum 		= getSlotNumber(evt.clientY + vertPad);
	foundSlot = null;
	openSlot = null;
	
	containerObjCenter 		= posY + slotHeight/2;
	
	// Capture mousemove event and tie it to moveSlot()
	document.onmousemove = moveSlot;
}

// Trigered when mouse is moving, handles movement of contianer, and how other slots interact while movement occurs
function moveSlot(evnt) {
	evt = (document.all) ? window.event : evnt;
	
	// Dynamically set coord values for use in moving container
	var posX 	= slotLeft + evt.clientX - downMouseX;
    var posY 	= slotTop + evt.clientY - downMouseY;
	var horzPad = 0;
	var slotCtrX = posX + slotObjCentr;

	// Dynamically calculate container boundaries
	var containerRight 	= evt.clientX + (containerWidth - downMouseX) + 2;
	var containerLeft 	= evt.clientX -  downMouseX;

	// Determine which side of the screen container center is at time event is fired
	if (slotCtrX < centr) {
		var half = 'L';

		if (posX <= 0) {
			// User is approching left boundary (horzPad prevents horizontal scrolling)
			var horzPad = posX;
		}
		
		// Test if a multi sort of slots occured on opposite side, yet and event has caught up with this side
		if (retainSide != half) {
			unDoSlots(retainSide);
		}
	} else {
		var half = 'R';
		var rightEdge = evt.clientX + containerWidth - (downMouseX - slotLeft);
		if (rightEdge >= winW) {
			// User is approching right boundary (horzPad prevents horizontal scrolling)
			var horzPad = rightEdge - winW;
		}

		// Test if a multi sort of slots occured on opposite side, yet and event has caught up with this side
		if (retainSide != half) {
			unDoSlots(retainSide);
		}
	}

	// Set position of container
	var containerObjSty 	= containerObj.style;
	containerObjSty.left 	= posX - horzPad;
	containerObjSty.top 	= posY;
	containerObjCenter 		= posY + slotHeight/2;
	
	var potentialSlotNum = getSlotNumber(containerObjCenter + vertPad);	
	var potentialSlotMetrics = getSlotCoords(potentialSlotNum);
	
	if (slotDataStr[dd_page][half][potentialSlotNum]['cell'] != "") {
		// Current cell is empty
		// Going upwards		
		if (containerObjCenter > potentialSlotMetrics['center']) {
			if ((potentialSlotNum < 18) && (slotDataStr[dd_page][half][potentialSlotNum+1]['cell'] == "")) {
				var nextSlotNum = potentialSlotNum + 1;
				swapSlotsInData(half, nextSlotNum, potentialSlotNum);
			} else {
				i = potentialSlotNum;
				found = false;
				while ((i > 1) && (!found)) {
					if (slotDataStr[dd_page][half][i]['form'] == "") {
						found = true;
						if (retainSide != half) {
							foundSlot = i;
							openSlot = potentialSlotNum;
						}
						while (i < potentialSlotNum) {
							swapSlotsInData(half, i, i+1);
							i++;
						}
					}
					i--;
				}
				
				if (!found) {
					i = potentialSlotNum;
					found = false;
					while ((i < 18) && (!found)) {
						if (slotDataStr[dd_page][half][i]['form'] == "") {
							found = true;
							if (retainSide != half) {
								foundSlot = i;
								openSlot = potentialSlotNum;
							}
							while (i > potentialSlotNum) {
								swapSlotsInData(half, i, i-1);
								i--;
							}
						}
						i++;
					}
				}

			}
		} else {
			// going down
			if (potentialSlotNum > 1 && slotDataStr[dd_page][half][potentialSlotNum-1]['cell'] == "") {
				var nextSlotNum = potentialSlotNum - 1;
				swapSlotsInData(half, nextSlotNum, potentialSlotNum);
			} else {
				//alert(2);
				i = potentialSlotNum;
				found = false;
				while ((i < 18) && (!found)) {
					if (slotDataStr[dd_page][half][i]['form'] == "") {
						found = true;
						if (retainSide != half) {
							foundSlot = i;
							openSlot = potentialSlotNum;
						}
						while (i > potentialSlotNum) {
							swapSlotsInData(half, i, i-1);
							i--;
						}
					}
					i++;
				}
				
				if (!found) {
					i = potentialSlotNum;
					found = false;
					while ((i > 1) && (!found)) {
						if (slotDataStr[dd_page][half][i]['form'] == "") {
							found = true;
							if (retainSide != half) {
								foundSlot = i;
								openSlot = potentialSlotNum;
							}
							while (i < potentialSlotNum) {
								swapSlotsInData(half, i, i+1);
								i++;
							}
						}
						i--;
					}
				}
			}
		}
	} else {
		if (containerObjCenter > potentialSlotMetrics['center']) {
			if ((potentialSlotNum < 18) && (slotDataStr[dd_page][half][potentialSlotNum+1]['cell'] == "")) {
				var nextSlotNum = potentialSlotNum + 1;
			} else {
				var nextSlotNum = potentialSlotNum - 1;
			}
		} else {
			if (potentialSlotNum > 1 && slotDataStr[dd_page][half][potentialSlotNum-1]['cell'] == "") {
				var nextSlotNum = potentialSlotNum - 1;
			} else {
				var nextSlotNum = potentialSlotNum + 1;
			}
		}
		
		if (nextSlotNum < 1) {
			var nextSlotNum = 1;
		}
		
		if (nextSlotNum > 18) {
			var nextSlotNum = 18;
		}
				
		swapSlotsInData(half, nextSlotNum, potentialSlotNum);
	}
		
	if (evt.clientX > winW) {
		// If user moves mouse out of window to right, drop slot
		releaseSlot(evt);
	}

	if (evt.clientX < 2) {
		// If user moves mouse out of window to left, drop slot (Does not always work)
		releaseSlot(evt);
	}

	// Store half for current event as last known horizontal position
	retainSide = half;
}

function swapSlotsInData(half, nextSlotNum, potentialSlotNum) {	
	if (slotDataStr[dd_page][half][nextSlotNum]['form'] == "") {
		var tempArray = slotDataStr[dd_page][half][nextSlotNum];
		slotDataStr[dd_page][half][nextSlotNum] = slotDataStr[dd_page][half][potentialSlotNum];
		slotDataStr[dd_page][half][potentialSlotNum] = tempArray;
	}
	
	var nextSlotObj 		= document.getElementById(half + nextSlotNum);
	var nextSlotSty			= nextSlotObj.style;
	var potentialSlotObj 	= document.getElementById(half + potentialSlotNum);
	var potentialSlotSty	= potentialSlotObj.style;
		
	// Full Slot
	nextSlotObj.innerHTML 			= slotDataStr[dd_page][half][nextSlotNum]['cell'];
	if (slotDataStr[dd_page][half][nextSlotNum]['cell'] != "") {
		nextSlotSty.backgroundColor 	= defaultBackgroundColor;
		nextSlotSty.borderColor 		= defaultBorderColor;
	} else {
		nextSlotSty.backgroundColor 	= emptyBackgroundColor;
		nextSlotSty.borderColor 		= emptyBorderColor;
	}
		
	// Empty Slot
	potentialSlotObj.innerHTML 			= slotDataStr[dd_page][half][potentialSlotNum]['cell'];
	potentialSlotSty.backgroundColor 	= emptyBackgroundColor;
	potentialSlotSty.borderColor 		= targetBorderColor;
}

function getSlotCoords(slotNum) {
	var coords = new Array();
	
	var slotTop = stackTop + (slotNum-1) * slotHeight;
	coords['top'] = slotTop;
	coords['center'] = slotTop + slotHeight/2;
	coords['bottom'] = slotTop + slotHeight;
	
	return coords;
}

// Trigered when mouse button is released, Set properties of slot where contianer is dropped and refreshes data structure
function releaseSlot(evnt) {

	evt = (document.all) ? window.event : evnt;
	foundSlot = null;
	openSlot = null;
	if (document.all) {
		// Browser is IE
		if (evt.button > 1) {
			// User is trying to use buttons (or wheel) other than the left
			return false;
		}
		
	} else {
		// Mozilla
		if (evt.button > 0) {
			// User is trying to use buttons (or wheel) other than the left
			return false;
		}
	}
	
	if (typeof(clickNum) == "undefined" || clickNum > 1) {
		// User is trying to double click before moving slot
		return false;
	}
	
	clickNum++;
	
	// Release mouse move event
	document.onmousemove = new Function("return false");
	document.onmousewheel = new Function("return true");
	
	// Set propeties of slot where container was dropped over
	var destSlotNum = null
	var destSlotNum = getSlotNumber(containerObjCenter + vertPad);
	
	if (slotDataStr[dd_page][retainSide][destSlotNum]['cell'] == "") {
		// Deposit contents of buffer into destination slot (Normal Behavior)
		populateFromBuffer(destSlotNum);
	} else {
		// Destination slot was not cleared when user released mouse (Abnormal Behavior most likely due to moving mouse too fast)
		alert('Your mouse movements may be too fast.');	
		if (destSlotNum && slotDataStr[dd_page][retainSide][destSlotNum]['cell'] == "") {
			// Recover if a slot number is available and that slot is empty
			populateFromBuffer(destSlotNum);
		} else {
			// Recover by looping through all slots on that side and finding an empty slot
			for (var destSlotNum in slotDataStr[dd_page][retainSide]) {
				if (slotDataStr[dd_page][retainSide][destSlotNum]['cell'] == "") {
					populateFromBuffer(destSlotNum);
					break;
				}		
			}
		}
	}
	//drawStr(slotDataStr);
	resetSlotMouseDowns();
	// Clear buffer (resets properties of container)
	buffer = null;
	isDown = false;
}

function resetSlotMouseDowns() {
	for (var side in slotDataStr[dd_page]) {
		for (var slotNum in slotDataStr[dd_page][side]) {
		    // Prototype Bug Fix:
		    if (slotNum == "each" || slotNum == "prototype")
		        break;
			slotObj = document.getElementById(side + slotNum);
			if (slotDataStr[dd_page][side][slotNum]['cell'] != "") {
				slotObj.onmousedown = selectSlot;
				slotObj.style.backgroundColor 	= defaultBackgroundColor;
				slotObj.style.borderColor 		= defaultBorderColor;
			} else {
				slotObj.onmousedown = new Function("return false");
				slotObj.style.backgroundColor 	= emptyBackgroundColor;
				slotObj.style.borderColor 		= emptyBorderColor;
			}
		}	
	}	
}

function populateFromBuffer(destSlotNum) {		
	slotDataStr[dd_page][retainSide][destSlotNum] = buffer;
	
	var destSlotObj 					= document.getElementById(retainSide + destSlotNum);
	destSlotObj.innerHTML 				= slotDataStr[dd_page][retainSide][destSlotNum]['cell'];
	destSlotObj.style.backgroundColor 	= defaultBackgroundColor;
	destSlotObj.style.borderColor 		= defaultBorderColor;
	
	destSlotObj.onmousedown = selectSlot;
	
	containerObj.style.zIndex 		= 0;
	containerObj.style.visibility 	= 'hidden';
	containerObj.style.left 		= 0;
	containerObj.style.top 			= 0;
	containerObj.innerHTML 			= '';
}

	
// Updates slot data structure based on state of slots
function updateSlotData() {
	return false;
	// Loop through slot data structure
	for (var partNum in slotDataStr) {
		if (partNum != dd_page) {
			continue;
		}

		for (var side in slotDataStr[partNum]) {
			for	(var i in slotDataStr[partNum][side]) {
				var cellObj = document.getElementById(side + i);
				if (cellObj.innerHTML) {
					// Data exists for this slot, capture event and store value in data structure
					cellObj.onmousedown = selectSlot;
					slotDataStr[partNum][side][i]['cell'] = cellObj.innerHTML;
				} else {
					// Slot is empty, release all events and clear value out of data structure
					cellObj.onmousedown = new Function("return false");
					cellObj.onmouseup 	= new Function("return false");
					cellObj.onmousemove = new Function("return false");
					slotDataStr[partNum][side][i]['cell'] = '';
				}
			}
		}
	}
}

// Reverts all slots on given side, back to last known state
function unDoSlots(half) {
	//foundSlot = i;
	//openSlot = potentialSlotNum;
	
	if (openSlot > foundSlot) {
		var i = openSlot;
		//alert(i + ' ' + foundSlot);
		while (i > foundSlot) {
			var prev = i-1;
			var tempArray = slotDataStr[dd_page][half][i];
			slotDataStr[dd_page][half][i] = slotDataStr[dd_page][half][prev];
			slotDataStr[dd_page][half][prev] = tempArray;
			i--;
		} 
	} else {
		var i = openSlot;
		while (i < foundSlot) {
			var nxt = i+1;
			var tempArray = slotDataStr[dd_page][half][i];
			slotDataStr[dd_page][half][i] = slotDataStr[dd_page][half][nxt];
			slotDataStr[dd_page][half][nxt] = tempArray;
			i++;
		} 
	}
	
	refreshView(half);
}

function refreshView(half) {    
	for (var num in slotDataStr[dd_page][half]) {
		var slotObj = document.getElementById(half + num);
		var slotSty = slotObj.style;
		slotObj.innerHTML = slotDataStr[dd_page][half][num]['cell'];
		
		if (slotDataStr[dd_page][half][num]['cell'] == "") {
			slotSty.backgroundColor = emptyBackgroundColor;
			slotSty.borderColor 	= emptyBorderColor;
		} else {
			slotSty.backgroundColor = defaultBackgroundColor;
			slotSty.borderColor 	= defaultBorderColor;
		}
	}
}

// Attempts to push all slots down one place
function lookDown(half, priNum, slotArray) {
	var emptySlots = true;
	// Loop down through current half of slot data structure starting from point of insertion
	for (var i=priNum;i<slotArray[dd_page][half].length;i++) {
		var curSlotObj = document.getElementById(half + i);
		if (i != priNum && !curSlotObj.innerHTML) {
			// An empty slot has been found that is not the same as the one entered
			var empty = i;
			emptySlots = false;
			// Start second loop reversing direction from empty slot back to point of insertion
			for (var n=empty;n>priNum;n--) {
				// Replace current slot with one just above it
				var priorNum = n - 1;
				var newSlotObj = document.getElementById(half + n);
				var newSlotSty = newSlotObj.style;
				slotDataStr[dd_page][half][priNum]['num'] = priorNum;
				newSlotObj.innerHTML 		= document.getElementById(half + priorNum).innerHTML;
				newSlotSty.borderColor 		= defaultBorderColor;
				newSlotSty.backgroundColor 	= defaultBackgroundColor;
			}
			break;
		}
	}

	return emptySlots;
}

// Attempts to push all slots up one place
function lookUp(half, priNum) {
	noEmptySlots = false;
	// Loop up through current half of slot data structure starting at point of insertion
	for (var i=priNum;i>0;i--) {
		var curSlotObj = document.getElementById(half + i);
		if (i != priNum && !curSlotObj.innerHTML) {
			// An empty slot has been found that is not the same as the one entered
			var empty = i;
			noEmptySlots = true;
			// Start second loop reversing direction from empty slot back to point of insertion
			for (var n=empty;n<priNum;n++) {
				// Replace current slot with one just below it
				var nextNum 	= n + 1;
				var newSlotObj 	= document.getElementById(half + n);
				var newSlotSty 	= newSlotObj.style;
				slotDataStr[dd_page][half][priNum]['num'] = nextNum;
				newSlotObj.innerHTML 		= document.getElementById(half + nextNum).innerHTML;
				newSlotSty.borderColor 		= defaultBorderColor;
				newSlotSty.backgroundColor 	= defaultBackgroundColor;
			}
			break;
		}
	}

	return noEmptySlots;
}

// Returns current slot number
function getSlotNumber(Ycoord) {	
	var slotNumber = (Ycoord - stackTop)/slotHeight;
	if (slotNumber > 18) {
		slotNumber = 18;
	}
	
	if (slotNumber < 1) {
		slotNumber = 1;
	}
	return Math.ceil(slotNumber);
}

// Checks if a vertical scroll bar exists and dynamicly compensates
function checkVerticalScroll(half, slotNum) {
	var targetSlot = slotDataStr[dd_page][half][slotNum];
	var topBound = targetSlot['center'];

	if (downMouseY < topBound) {
		// Verstical scroll exist, pad as needed
		return topBound - downMouseY;
	} else {
		return 0;
	}
}

