/* Initialize the dragger class for the defined sections on a profile page.
 * param	profileId		Optional. The ID of the profile to update (required if updateDB is set).
 * param	updateDB		Optional. Set to true if the database should be updated (default is false).
 * param	sectionClass	Optional. The class name used for the sections in the profile (default is 'drag').
 * param	tag				Optional. The tag used for the sections in the profile (default is 'div').
 * param	debug			Optional. If true, then debugging info will display in the browser status bar (default is true).
 * param	callback		Optional. The name of the user-defined function to call when we start/stop dragging an item.
 */
function Dragger( profileId, updateDB, sectionClass, tag, debug, callback ) {
	if ( typeof( updateDB ) == "undefined" ) updateDB = true;
	if ( typeof( sectionClass ) == "undefined" ) sectionClass = "drag";
	if ( typeof( tag ) == "undefined" ) tag = "div";
	if ( typeof( debug ) == "undefined" ) debug = false;
	if ( typeof( callback ) == "undefined" ) callback = null;

	var sections = new Array( "dummy" );  // dummy item added to fix a bug when dragging on top of the first item.
	var fromSection = null;
	var dragSection = null;
	var placeholderSection = null;
	var mouseOffset = null;

	sectionList = document.getElementsByTagName( tag );
	for ( var i = 0; i < sectionList.length; i++ ) {
		classes = sectionList[i].className.split( " " );
		for ( var j = 0; j < classes.length; j++ ) {
			if ( classes[j] == sectionClass ) {
				sections.push( sectionList[i] );
				if ( !sectionList[i].id ) continue;

				// Set handlers for mouseover, mouseout and mousedown
				sectionList[i].onmouseover = function( event ) {
					this.className = this.className.replace( sectionClass, sectionClass + "_hover" );
				}
				sectionList[i].onmouseout = function( event ) {
					this.className = this.className.replace( sectionClass + "_hover", sectionClass );
				}

				subsections = sectionList[i].getElementsByTagName( "div" );
				for ( var k = 0; k < subsections.length; k++ ) {
					if ( subsections[k].className.search( "section_head" ) > -1 ) {
						subsections[k].onmousedown = function( event ) {
							this.className = this.className.replace( sectionClass + "_hover", sectionClass );
							initDrag( this.parentNode, event );
							return false;
						}
					}
				}
			}
		}
	}

	function initDrag( section, event ) {
		document.onmousemove = mouseMove;
		document.onmouseup = mouseUp;
		fromSection = section;
		mouseOffset = getMouseOffset( section, event );
		dragSection = section.cloneNode( true );
		placeholderSection = section.cloneNode( true );
		document.body.appendChild( dragSection );
		document.body.appendChild( placeholderSection );
		fromSection.style.display = "none";
		dragSection.className += " dragitem";
		dragSection.style.display = "none";
		dragSection.style.width = parseInt( fromSection.parentNode.offsetWidth ) + "px";
		placeholderSection.className += " placeholder";
		placeholderSection.style.display = "none";
		mouseMove( event );
		if ( callback != null ) {
			if ( eval( 'typeof(' + callback + ')') == 'function' ) {
				callback();
			} else {
				alert( "Invalid callback function: " + callback );
			}
		}
		if ( debug ) window.status = "inti drag: " + section.id;
	}

	function mouseMove( event ) {
		event = event || window.event;
		var mousePos = mouseCoords( event );
		if ( fromSection ) {
			if ( debug ) window.status = "dragging: " + fromSection.id + " (" + mousePos.x + "," + mousePos.y + ") (b: " + (document.body.scrollTop + document.body.clientHeight) + ")";
			dragSection.style.display = "";
			dragSection.style.top = mousePos.y - mouseOffset.y + "px";
			dragSection.style.left = mousePos.x - mouseOffset.x + "px";

			/* use documentElement for IE7 with XHTML 1.0 doctype */
			if ( document.documentElement ) {
				var bottom = document.documentElement.scrollTop + document.documentElement.clientHeight;
				if ( mousePos.y <= document.documentElement.scrollTop && mousePos.y > 20 ) {
					window.scrollBy( 0, -20 );
				} else if ( mousePos.y >= bottom  && mousePos.y < bottom + 20 ) {
					window.scrollBy( 0, 20 );
				}
			} else {
				var bottom = document.body.scrollTop + document.body.clientHeight;
				if ( mousePos.y <= document.body.scrollTop && mousePos.y > 20 ) {
					window.scrollBy( 0, -20 );
				} else if ( mousePos.y >= bottom  && mousePos.y < bottom + 20 ) {
					window.scrollBy( 0, 20 );
				}
			}
			checkDropSection( mousePos );
			return false;
		}
	}

	function mouseUp( event ) {
		event = event || window.event;
		var mousePos = mouseCoords( event );
		if ( fromSection ) {
			if ( callback != null ) {
				if ( eval( 'typeof(' + callback + ')') == 'function' ) {
					callback();
				} else {
					alert( "Invalid callback function: " + callback );
				}
			}
			var dropSection = checkDropSection( mousePos );
			if ( dropSection ) {
				if ( debug ) window.status = fromSection.id + " dropped in section: " + dropSection.id;
				dropSection.parentNode.insertBefore( fromSection, dropSection );
				if ( updateDB ) updateDatabase( fromSection.id, dropSection.id, dropSection.parentNode.className );
			}
			document.body.removeChild( dragSection );
			placeholderSection.parentNode.removeChild( placeholderSection );
			fromSection.style.display = "";
			fromSection = null;
		}
	}

	function checkDropSection( pos ) {
		var fixedColumn = false;
		classes = fromSection.className.split( " " );
		for ( var i = 0; i < classes.length; i++ ) {
			if ( classes[i] == "fixed_col" ) fixedColumn = true;
		}
		for( var i = 0; i < sections.length; i++ ) {
			var targPos = getPosition( sections[i] );
			var targWidth = parseInt( sections[i].offsetWidth );
			var targHeight = parseInt( sections[i].offsetHeight );
			if (( pos.x > targPos.x ) && ( pos.x < ( targPos.x + targWidth )) && ( pos.y > targPos.y ) && ( pos.y < ( targPos.y + targHeight ))) {
				if ( fixedColumn ) {
					colPos = getPosition( fromSection.parentNode );
					colWidth = parseInt( fromSection.parentNode.offsetWidth );
					if (( pos.x < colPos.x ) || ( pos.x > ( colPos.x + colWidth ))) {
						if ( debug ) window.status = "This section cannot change columns";
						return null;
					}
				}
				if ( debug ) window.status = "drop over section: " + sections[i].id + " ("+(targWidth+targPos.x)+","+(targHeight+targPos.y)+")";
				sections[i].parentNode.insertBefore( placeholderSection, sections[i] );
				placeholderSection.style.display = "";
				dragSection.style.display = "none";
				return sections[i];
			} else {
				placeholderSection.style.display = "none";
				dragSection.style.display = "";
			}
		}
		return null;
	}

	function updateDatabase( fromId, dropId, columnClass ) {
		from = fromId.split( "_" );
		column = columnClass.split( "_" );
		dropName = "last_" + column[1];
		if ( dropId ) {
			drop = dropId.split( "_" );
			dropName = drop[1];
		}
		ajax = new Ajax();
		ajax.post( 
			SYSTEM_URL + "/includes/update_profile_sections.php", updateCallback, [
				[ "function", "move" ],
				[ "profileId", encodeURI( profileId )],
				[ "pageName", encodeURI( from[0] )],
				[ "sectionName", encodeURI( from[1] )],
				[ "dropName", encodeURI( dropName )]
			]
		);
	}

	function updateCallback( html ) {
		if ( debug ) alert( html );
	}

	function getMouseOffset( target, event ) {
		event = event || window.event;
		var docPos = getPosition( target );
		var mousePos = mouseCoords( event );
		return { x:mousePos.x - docPos.x, y:mousePos.y - docPos.y }
	}

	function getPosition( target ) {
		var left = 0;
		var top = 0;
		while( target.offsetParent ) {
			left += target.offsetLeft;
			top += target.offsetTop;
			target = target.offsetParent;
		}
		left += target.offsetLeft;
		top += target.offsetTop;
		return { x:left, y:top }
	}

	function mouseCoords( event ) {
		if ( event.pageX || event.pageY ) { 
			return { x:event.pageX, y:event.pageY }
		}
		/*use documentElement for IE7 with XHTML 1.0 doctype */
		if ( document.documentElement ) {
			return {
				x:event.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft, 
				y:event.clientY + document.documentElement.scrollTop - document.documentElement.clientTop
			}
		} else {
			return {
				x:event.clientX + document.body.scrollLeft - document.body.clientLeft, 
				y:event.clientY + document.body.scrollTop - document.body.clientTop
			}
		}
	}
}
