/**
 * The (category) node from the tree that has been clicked.
 */
var contentSourceSelectedTreeNode = false;
var contentSourceSelectedTreeNodeId = '';

/**
 * Handler that is called when item is selected (see showContentSourceBrowser())
 */
var contentSourceSelectHandler = false;

/**
 * Desired width, height and widht/height type of the selectd image (see showContentSourceBrowser())
 */
var contentSourceDesiredWidth = 0;
var contentSourceDesiredHeight = 0;
var contentSourceDesiredWHtype = '';
var contentSourceDesiredColorType = '';
var contentSourceBaseAlbumIds = false;
var contentSourceContentIds = false;
var contentSourceForceCrop = true;
var contentSourceCropType = 'aspectratio'; 		// aspectratio / freehand

/**
* Desired color spaces seperated by commas (cmyk,rgb,bw)
*/
var contentSourceDesiredColorSpaces = '';

/**
 * Desired DPI (whtype must be inches)
 */
var contentSourceMinDPI = 0;

/**
 * True if currently in edit mode
 */
var contentSourceEditMode = false;

/**
 * False if not writable directories exist.
 */
var contentSourceAllowEditing = true;  

/**
 * True if the image was edited
 */
var contentSourceItemEdited = false;

/**
 * Array containing warnings for the current selected image
 */
var contentSourceItemWarnings = new Array();


/**
 * The desired aspect ratio of the crop area.
 */
var cropAspectRatio = 0;

/**
 * Internal variables used while cropping and maintaining aspect ratio
 */
var newCropAreaWidth;
var newCropAreaHeight;
var cropAreaResizeX;
var cropAreaResizeY;
var cropResizeEdges;
var oldCropResizeEdges;
var cropMouseOverX;
var cropMouseOverY;

/**
* Internal var that is set to prevent open/close event to trigger opening category content
*/
var contentSourceOpenCloseCategory = false;

/**
 * Internal vars that is used to remember the selected content source code and categoryid
 */
var contentSourceSelectededCnsCode = '';
var contentSourceSelectededCategoryId = 0;

/**
 * If true, show the user category in the category explorer
 */
var contentSourceShowUserCategory = true;

/**
 * Open the content source browser
 * 
 * @param selectHandler handler that receives the SelectedItem object
 * @param actions comma separated list of allowed actions
 * @param params array containing the following params
 * - width : desired width of the image
 * - height : desired height of the image
 * - whtype : the width/height type (units, pixels or inches)
 * - colortype : FC, BW or PMS
 * - min_pdi : the minimal dpi of the image (whtype must be inches!)
 * - colorspaces : the required colorspaces, seperated by commas (cmyk,rgb,bw)
 */
function showContentSourceBrowser(selectHandler, actions, params) {
	
	contentSourceSelectHandler = selectHandler;

    bb.document.getElementById('loadingMessageCommon').show();

	if(params) {
		
		if(params['width']) {
			contentSourceDesiredWidth = params['width'];
		} else {
			contentSourceDesiredWidth = '';
		}

		if(params['height']) {
			contentSourceDesiredHeight = params['height'];
		} else {
			contentSourceDesiredHeight = '';
		}

		if(params['whtype']) {
			contentSourceDesiredWHtype = params['whtype'];
		} else {
			contentSourceDesiredWHtype = '';
		}
		
		if(params['colortype']) {
			contentSourceDesiredColorType = params['colortype'];
		} else {
			contentSourceDesiredColorType = '';
		}
		
		if(params['min_dpi']) {
			if(params['whtype'] != 'inches') {
				alert('whtype argument must be inches for min_dpi');
				return;
			}
			contentSourceMinDPI = params['min_dpi'];
		}
		else {
			contentSourceMinDPI = 0;
		}
		
		if(params['colorspaces']) {
			contentSourceDesiredColorSpaces = params['colorspaces'];
		}
		else {
			contentSourceDesiredColorSpaces = '';
		}
		
		if(params['basealbumids']) {
			contentSourceBaseAlbumIds = params['basealbumids'];
		}
		else {
			contentSourceBaseAlbumIds = false;
		}
		
		if(params['contentids']) {
			contentSourceContentIds = params['contentids'];
		}
		else {
			contentSourceContentIds = false;
		}
		
		if(params['forcecrop'] != undefined) {
			contentSourceForceCrop = params['forcecrop'];
		}
		else {
			contentSourceForceCrop = false;
		}
		
		if(params['croptype'] != undefined) {
			contentSourceCropType = params['croptype'];
		}
		else {
			contentSourceCropType = 'aspectratio';
		}
		
		if(params['showusercategory'] != undefined) {
			contentSourceShowUserCategory = params['showusercategory']; 
		} 
		else {
			contentSourceShowUserCategory = true; 
		}
	}
	else {
		contentSourceDesiredWidth = 0;
		contentSourceDesiredHeight = 0;
		contentSourceDesiredWHtype = '';
		contentSourceDesiredColorType = '';
		contentSourceMinDPI = 0;
		contentSourceDesiredColorSpaces = '';
        contentSourceBaseAlbumIds = false;
        contentSourceContentIds = false;
        contentSourceForceCrop = false;
        contentSourceCropType = 'aspectratio';
        contentSourceShowUserCategory = true;
	}
	
	contentSourceItemEdited = false;
    contentSourceEditMode = false;
	
	var url = '/default/contentsource/index/view/modal';
	
	// set actions
	if(actions) {
		url += '/actions/'+actions.toString();
	}
	
	if(contentSourceBaseAlbumIds) {
		url += '/basealbumids/'+contentSourceBaseAlbumIds;
	}
	
	if(contentSourceContentIds) {
		url += '/contentids/'+contentSourceContentIds;
	}
	
	if(contentSourceShowUserCategory && contentSourceShowUserCategory != 'false') {
		url += '/showusercategory/'+contentSourceShowUserCategory;
	}
	
	blockUserInput();
	
	bb.command.load(url, 'POST', '', null, bb.document.getElementById('modalPlaceHolder'), 'replaceChildren');
}

/**
 * Event that is raised on the content source modal once the image has been picked.
 * 
 * @param cns_code of the content source
 * @param id id of the content
 * @param content url to the content
 * @param preview url to the preview
 * @param warnings array of warnings
 * @param webparams object with webparams (margin, padding, border, alt)
 */
function SelectedItem(cns_code, id, content, preview, mimeType, warnings, webparams) {
	
	this.cns_code = cns_code;

	this.id = id;
	
	this.content = content;
	
	this.preview = preview;

	this.mimeType = mimeType;
	
	this.warnings = warnings;
	
	/**
	 * weboptions are: margin, padding, border, alt
	 */
	this.webparams = webparams;
}

/**
 * Shows buttons to accept or decline edit operations.
 * This function will disable all controls (input)
 * 
 */
function startEditMode() {
	
	if(contentSourceAllowEditing) {

        contentSourceEditMode = true;

		bb.document.getElementById('contentSourceEditButtons').viewNode.style.display = 'block';
		
		var actionControls = _getActionControls();
		
		for(i in actionControls) {
			if(typeof actionControls[i] == 'function') continue;
			
			if(actionControls[i].getProperty('tagName') == 'input' || actionControls[i].getProperty('tagName') == 'textarea') {
				actionControls[i].viewNode.disabled = "disabled";
			}
			else {
				actionControls[i].setProperty('disabled', true);
			}
		}
		
		// fire the "endEditMode" event on the "contentEdit" element
		_fireContentEditEvent("startEditMode");
	}
	else {
	
		alert('Sorry this function is disabled');
	}
}

/**
 * Shows buttons to accept or decline edit operations.
 * 
 */
function endEditMode() {
	
	var actionControls = _getActionControls();
	
	for(i in actionControls) {
		if(typeof actionControls[i] == 'function') continue;
		
		if(actionControls[i].getProperty('tagName') == 'input' || actionControls[i].getProperty('tagName') == 'textarea') {
			actionControls[i].viewNode.disabled = "";
		}
		else {
			actionControls[i].setProperty('disabled', false);
		}
	}
	
	// fire the "endEditMode" event on the "contentEdit" element
	_fireContentEditEvent("endEditMode");

    contentSourceEditMode = false;
}

/**
 * Get all action controls (input and buttons)
 * 
 */
function _getActionControls() {
	
	var contentSourceActions = bb.document.getElementById('tabBoxContentEditOptions');
	
	var actionControls = bb.evaluate("descendant::*[name()='input' or name()='textarea' or name()='b:button' or name()='b:comboBox']", contentSourceActions.modelNode, contentSourceActions.modelNode);
	
	for(i in actionControls) {
		if(typeof actionControls[i] == 'function') continue;
		
		actionControls[i] = bb.getControllerFromModel(actionControls[i]);
	}
	
	return actionControls;
}

/**
 * Fire a event on the "contentEdit" element
 * 
 * @param type type of the event
 */
function _fireContentEditEvent(type) {
	
	// fire the "startEditMode" event on the "contentEdit" element
	var oEvent = bb.document.createEvent("Events")
	oEvent.initEvent(type,false,false)
	                       
	var myElem = bb.document.getElementById("contentEdit")
	myElem.dispatchEvent(oEvent);
}

/**
 * Calcluate the dpi usng the image size and the box size
 * 
 * @param imageWidth
 * @param imageHeight
 * @return
 */
function calculateDPI(imageWidth, imageHeight) {

	if(contentSourceDesiredWHtype != 'inches') {
		alert('whtype must be inches');
		return;
	}
	
	if(contentSourceDesiredWidth == 0 || contentSourceDesiredHeight == 0) {
	
		alert('desired width and height (inches) must be set');
		return;
	}
	
	return Math.ceil(Math.min(imageWidth / contentSourceDesiredWidth, imageHeight / contentSourceDesiredHeight));
}

/**
 * Update the edit preview after doing a edit operation.
 * 
 */
function updatePreview() {

	var image = bb.document.getElementById('contentSourceEditPreviewImage').viewNode;
	var src = new String(image.src);
	var idxOfTimestamp = src.indexOf('?d=');
	var url = src.substring(0, idxOfTimestamp);
	
	image.src = url+'?d='+new Date().getTime();
}

/**
 * Accepts image edit by copying edited image to original and hiding edit buttons.
 */
function acceptEdit() {
	
	bb.document.getElementById('contentSourceEditButtons').viewNode.style.display = 'none';

	bb.document.getElementById('loadingMessageApplyingEdit').show();

	_fireContentEditEvent("acceptEdit");
}

/**
 * Decline image edit by copying original image to edited image and hiding edit buttons.
 */
function declineEdit() {
	
	bb.document.getElementById('contentSourceEditButtons').viewNode.style.display = 'none';

	_fireContentEditEvent("declineEdit");

	bb.command.load('/default/contentsource/undoedit', 'POST', '', null, null, '', updatePreview);
	endEditMode();
}

/**
 * Update the preview and hide loading message. (Called by applyRotate, applyCrop...)
 * 
 * @return
 */
function applyReady() {
	
	updatePreview();
	bb.document.getElementById('loadingMessageApplyingEdit').hide();
	endEditMode();
}

/**
 * Save edited image to a custom category, into hidden .edited category.
 */
function saveAndInsertImage(contentName, contentDescription, cnsCode, objectId, objectContent, objectPreview, objectMimeType, saveDerivative) {

	// if the content was edited, save the edited image (thus the supplied params cnsCode, objectId... will not be used)
	if(contentSourceItemEdited) {
		
		if(!saveDerivative) {
			saveDerivative = 'false';
		}
		
		var contentSourceCheckSave = bb.document.getElementById('contentSourceCheckSave');
		
		bb.document.getElementById('loadingMessageSavingImage').show();
		
		var categoryId = 0;
		
		if(contentSourceCheckSave.getProperty('checked')) {
			var selNode = bb.document.getElementById('contentSourceSelectSave').getProperty('selectedNode');
			var selNodeId = new String(selNode.getAttribute('id')).split('_');
			categoryId = selNodeId[1];
		}

		bb.command.load('/default/contentsource/save-edited-content/categoryid/'+categoryId+'/cns_code/'+contentSourceSelectedItemCnsCode+'/name/'+contentName+'/description/'+contentDescription+'/derivative/'+saveDerivative, 'GET', '', null, bb.document.getElementById('modalBrowseContentSource'), 'appendChild');
	}
	else {
		
		insertImage(cnsCode, objectId, objectContent, objectPreview, objectMimeType);
	}
}

/**
 * Function called by save-edited-content.phtml, or by saveAndInsertImage, to insert image.
 */
function insertImage(cnsCode, objectId, objectContent, objectPreview, objectMimeType) {
	
	bb.document.getElementById('loadingMessageSavingImage').hide();
	var modalBrowseContentSource = bb.document.getElementById('modalBrowseContentSource');
	
	if(modalBrowseContentSource) {
		modalBrowseContentSource.close();
	}
	
	if(contentSourceSelectHandler) {
		var selectedItem = new SelectedItem(cnsCode, objectId, objectContent, objectPreview, objectMimeType, contentSourceItemWarnings);
		contentSourceSelectHandler(selectedItem);
	}
	
}

var currentDegrees = 0;

/**
 * Initialize rotation
 */
function initRotation() {
	
	bb.document.getElementById('contentEdit').addEventListener('acceptEdit', applyRotate, false, false);
	bb.document.getElementById('contentEdit').addEventListener('endEditMode', endRotate, false, false);
	currentDegrees = 0;
}

/**
 * Preview rotation
 * 
 * @param degrees
 */
function previewRotate(degrees) {
	
	bb.command.load('/default/contentsource/rotate/mode/preview/degrees/'+degrees, 'POST', '', null, null, '', updatePreview);
	currentDegrees = (currentDegrees + Number(degrees)) % 360;
}

/**
 * Apply rotation
 * 
 * @param degrees
 */
function applyRotate() {

	contentSourceItemEdited = true;

	bb.command.load('/default/contentsource/rotate/mode/apply/degrees/'+currentDegrees, 'POST', '', null, null, '', applyReady);
}

/**
 * un-initialize rotation
 * 
 * @param degrees
 */
function endRotate() {
	
	// remove event listeners
	bb.document.getElementById('contentEdit').removeEventListener('acceptEdit', applyRotate, false, false);
	bb.document.getElementById('contentEdit').removeEventListener('endEditMode', endRotate, false, false);
}

/**
 * Initialize the crop area
 */
function initCropping() {
	
	var image = bb.document.getElementById('contentSourceEditPreviewImage');
	
	
	if(image.viewNode.offsetWidth == 0) {
		window.setTimeout(initCropping, 50);
		return;
	}
	
	var cropAreaBoundaries = bb.document.getElementById('crop-area-boundaries');
	var cropArea = bb.document.getElementById('crop-area');

	// set the desired crop aspect ratio (only when desired crop type = aspectratio) 
	if(contentSourceDesiredWidth && contentSourceCropType == 'aspectratio') {
		cropAspectRatio = contentSourceDesiredWidth / contentSourceDesiredHeight;
		cropAspectRatio = Math.round(cropAspectRatio * 100) / 100;
	}
	else {
		cropAspectRatio = 0;
	}

	// define the initial size of the crop area as a percentage of the image
	var cropAreaPerc = 0.8;

	// set dimensions of crop area boundaries
	cropAreaBoundaries.viewNode.style.width = image.viewNode.offsetWidth+'px';
	cropAreaBoundaries.viewNode.style.height = image.viewNode.offsetHeight+'px';
	cropAreaBoundaries.viewNode.style.left = image.viewNode.offsetLeft+'px';
	cropAreaBoundaries.viewNode.style.top = image.viewNode.offsetTop+'px';

    // if a crop aspect ratio is set, set the initial width & height according to the ratio
	if(cropAspectRatio) {
		
		// calculate the amount of pixels per unit
		var pixelsPerUnit;
		
		if(contentSourceDesiredWidth >= contentSourceDesiredHeight) {
			pixelsPerUnit = image.viewNode.offsetWidth / contentSourceDesiredWidth;
		}
		else {
			pixelsPerUnit = image.viewNode.offsetHeight / contentSourceDesiredHeight;
		}
		
		// determine the width & height of the croparea
		var cropAreaWidth = Math.round(pixelsPerUnit * contentSourceDesiredWidth);
		var cropAreaHeight = Math.round(pixelsPerUnit * contentSourceDesiredHeight);
		
		// calculate the current width/height, height/width ratios
		var heightWidthRatio = contentSourceDesiredHeight / contentSourceDesiredWidth;
		var widthHeightRatio = contentSourceDesiredWidth / contentSourceDesiredHeight;
	
		// now reduce the width & height of the crop area if they exceed the image width & height
		if(cropAreaWidth > image.viewNode.offsetWidth) {
			cropAreaWidth = image.viewNode.offsetWidth;
			cropAreaHeight = heightWidthRatio * cropAreaWidth;
		}

		if(cropAreaHeight > image.viewNode.offsetHeight) {
			cropAreaHeight = image.viewNode.offsetHeight;
			cropAreaWidth = widthHeightRatio * cropAreaHeight;
		}

        var cropAreaLeft = (image.viewNode.offsetWidth - cropAreaWidth) / 2;
        var cropAreaTop = (image.viewNode.offsetHeight - cropAreaHeight) / 2;
	}
	// else set the dimensions of the croparea to be a percentage of the image
	else {
		
		var cropAreaWidth = (image.viewNode.offsetWidth*cropAreaPerc);
		var cropAreaHeight = (image.viewNode.offsetHeight*cropAreaPerc);
		var cropAreaLeft = ((image.viewNode.offsetWidth*(1-cropAreaPerc))/2);
		var cropAreaTop = ((image.viewNode.offsetHeight*(1-cropAreaPerc))/2);
	}
		
	// set initial dimensions of crop area
	cropArea.viewNode.style.width = cropAreaWidth+'px';
	cropArea.viewNode.style.left = cropAreaLeft+'px';
	cropArea.viewNode.style.height = cropAreaHeight+'px';
	cropArea.viewNode.style.top = cropAreaTop+'px';

	// remove event listeners
	bb.document.getElementById('contentEdit').addEventListener('endEditMode', hideCropArea, false, false);
	bb.document.getElementById('contentEdit').addEventListener('acceptEdit', applyCrop, false, false);
}

/**
 * mouverover handler for the croparea, sets x & y to use later on
 * 
 * @param eve event
 */
function cropMouseOver(eve) {
	// remember the X + Y during mousemove, because for some reason they are not available upon resizeStart
	cropMouseOverX = eve.clientX;
	cropMouseOverY = eve.clientY;
}

function cropMouseDown(eve) {

    var cropArea = bb.document.getElementById('crop-area');

    detectCropResizeEdges(cropArea, cropMouseOverX, cropMouseOverY);

    if(!(cropResizeEdges.gripRight || cropResizeEdges.gripBottom)) {
 
        controller = eve.target;

        btl.drag.startPoint = {
                        startX: eve.pageX,
                        startY: eve.pageY,
                        controller: controller,
                        viewNode: eve.viewTarget //fix to start dragging
                    };

        bb.document.addEventListener('mousemove',   btl.drag.handleMouseMoveBeforeStart,  false);
        bb.document.addEventListener('mouseup',     btl.drag.handleMouseUpBeforeStart,  false);
        btl.drag.startDrag(eve);
    }
}

/**
 * please comment function
 * 
 * @param eve event
 * @return
 */
function cropDragEnd(eve) {

	var cropArea = bb.document.getElementById('crop-area');

	// below code is executed to prevent croparea to lose opacity
	eve.stopHorizontalPropagation();

	if (cropArea.viewNode.bPosition) {
		cropArea.viewNode.bPosition = false;
	}
	if(btl.drag._savedStyle && btl.drag._savedStyle.parentNode == document.head) {
		document.head.removeChild( btl.drag._savedStyle );
	}
	if(btl.drag.outlineElement) {
		btl.drag.outlineElement.style.left = '';
		btl.drag.outlineElement.style.top = '';
	}
	
	if(btl.drag.dragSymbol) {
		document.body.removeChild(btl.drag.dragSymbol);
		btl.drag.dragSymbol = null;
	}
}

/**
 * resizestart event handler for croparea. sets the initial x&y, width&height and detects the grid edges.
 */
function cropResizeStart() {
	
	if(cropAspectRatio) {
		var cropArea = bb.document.getElementById('crop-area');
	
		// upon restart, remember the starting X + Y, the edges of the resize operation and the width and height of the croparea
		cropAreaResizeX = cropMouseOverX;
		cropAreaResizeY = cropMouseOverY;
		detectCropResizeEdges(cropArea, cropMouseOverX, cropMouseOverY, true);
	
		newCropAreaWidth = cropArea.viewNode.offsetWidth;
		newCropAreaHeight = cropArea.viewNode.offsetHeight;
    }
}

/**
 * Resize event event handler for croparea. If the crop aspect ratio is set, it forces the ratio.
 * @param eve event
 */
function cropResize(eve) {
	
	if(cropAspectRatio) {
		/** 
		* catch the resize, prevent it and do the resize manually to maintain aspect ratio
		*/
		
		var cropArea = bb.document.getElementById('crop-area');
		var cropAreaBoundaries = bb.document.getElementById('crop-area-boundaries');
		var cropAreaBox = bb.html.getBoxObject(cropArea);
	
		var newCropAreaDeltaWidth = 0;
		var newCropAreaDeltaHeight = 0;
	
		// calculate the difference of height & width to apply				
		if(cropResizeEdges.gripRight) {
			newCropAreaDeltaWidth += (eve.pageX - cropAreaResizeX);
		}
		if(cropResizeEdges.gripBottom) {
			newCropAreaDeltaHeight += (eve.pageY - cropAreaResizeY);
		}

		// calculate the new width / height ratio
		var newCropAreaRatio =  Math.round(((newCropAreaWidth + newCropAreaDeltaWidth) / (newCropAreaHeight + newCropAreaDeltaHeight)) * 100) / 100;
	
		// calculate the current width/height, height/width ratios
		var heightWidthRatio = contentSourceDesiredHeight / contentSourceDesiredWidth;
		var widthHeightRatio = contentSourceDesiredWidth / contentSourceDesiredHeight;
		
		// if the new ratio is not the desired ratio
		if(newCropAreaRatio != cropAspectRatio) {
		
		 	// if the absolute delta width is the highest, correct the height accordingly
			if(Math.abs(newCropAreaDeltaHeight) >= Math.abs(newCropAreaDeltaWidth)) {
				newCropAreaDeltaWidth = newCropAreaDeltaHeight * widthHeightRatio;
			}
			else {
				newCropAreaDeltaHeight = newCropAreaDeltaWidth * heightWidthRatio;
			}
		}
	
		// apply the delta width & height
		newCropAreaWidth += newCropAreaDeltaWidth;
		newCropAreaHeight += newCropAreaDeltaHeight;
	
		// if the width is beyond the boundaries, correct it
		if(newCropAreaWidth + cropArea.viewNode.offsetLeft > cropAreaBoundaries.viewNode.offsetWidth) {
			newCropAreaWidth = cropAreaBoundaries.viewNode.offsetWidth - cropArea.viewNode.offsetLeft;
			newCropAreaHeight = newCropAreaWidth * heightWidthRatio;
		}
		
		// if the height is beyond the boundaries, correct it
		if(newCropAreaHeight + cropArea.viewNode.offsetTop > cropAreaBoundaries.viewNode.offsetHeight) {
			newCropAreaHeight = cropAreaBoundaries.viewNode.offsetHeight - cropArea.viewNode.offsetTop;
			newCropAreaWidth = newCropAreaHeight * widthHeightRatio;
		}
	
		// remeber the X + Y
		cropAreaResizeX = eve.pageX;
		cropAreaResizeY = eve.pageY;
	
		// apply the new width + height
		cropArea.viewNode.style.width = newCropAreaWidth+'px';
		cropArea.viewNode.style.height = newCropAreaHeight+'px';
		
		// prevent default behavior, as it doesn't maintain aspect ratio
		eve.preventDefault();	
	}
}

/**
 * Resizeend event handler for croparea. Forces the new width & height.
 * @param eve event
 */
function cropResizeEnd(eve) {

	if(cropAspectRatio) {
		var cropArea = bb.document.getElementById('crop-area');
		
		// now this is tricky. the original width + height must be set after the resizeEnd,
		// because the original width + height are applied first by the browser because of the preventDefault.
		window.setTimeout(function(){
			cropArea.viewNode.style.width = newCropAreaWidth+'px';
			cropArea.viewNode.style.height = newCropAreaHeight+'px';
		}, 10);
		eve.preventDefault();
	}
}


/**
 * Hide the crop area
 */
function hideCropArea() {

	var cropAreaBoundaries = bb.document.getElementById('crop-area-boundaries');
	if(cropAreaBoundaries) {
		cropAreaBoundaries.getProperty('parentNode').removeChild(cropAreaBoundaries);
	}

	bb.document.getElementById('contentEdit').removeEventListener('endEditMode', hideCropArea, false, false);
	bb.document.getElementById('contentEdit').removeEventListener('acceptEdit', applyCrop, false, false);
}

/**
 * Crop image by the dimensions of the crop area.
 * @return
 */
function applyCrop() {

	contentSourceItemEdited = true;
	
	var cropArea = bb.document.getElementById('crop-area');
	var cropAreaBoundaries = bb.document.getElementById('crop-area-boundaries');
	
	// calculate crop parameters in percentages
	
	var left = (cropArea.viewNode.offsetLeft ? 100 / (cropAreaBoundaries.viewNode.offsetWidth / cropArea.viewNode.offsetLeft) : 0);
	var top = (cropArea.viewNode.offsetTop ? 100 / (cropAreaBoundaries.viewNode.offsetHeight / cropArea.viewNode.offsetTop) : 0);
	
	var width = (cropArea.viewNode.offsetWidth ? 100 / (cropAreaBoundaries.viewNode.offsetWidth / cropArea.viewNode.offsetWidth) : 0);
	var height = (cropArea.viewNode.offsetHeight ? 100 / (cropAreaBoundaries.viewNode.offsetHeight / cropArea.viewNode.offsetHeight) : 0);

	// create url
	var url = '/default/contentsource/crop'+'/left/'+left+'/top/'+top+'/width/'+width+'/height/'+height;

	bb.command.load(url, 'POST', '', null, null, '', applyReady);
}

/**
* Detect the edges that are used to resize.
*
* - obj : object to detect resize edges
* - x & y : current x & y of resize operation
* - force : true if one of the resize edges MUST be set. if set, old resize edges are remembered if mouse leaves obj.
*/
function detectCropResizeEdges(obj, x, y, force) {

	var cropAreaBox = bb.html.getBoxObject(obj.viewNode);

	cropResizeEdges = new Object();

	if(x - Number(obj.getAttribute('resizeGripSize')) <= cropAreaBox.x && x + Number(obj.getAttribute('resizeGripSize')) >= cropAreaBox.x) {
		cropResizeEdges.gripLeft = true;
	}
	else {
		cropResizeEdges.gripLeft = false;
	}

	if(x - Number(obj.getAttribute('resizeGripSize')) <= cropAreaBox.x + cropAreaBox.width && x + Number(obj.getAttribute('resizeGripSize')) >= cropAreaBox.x + cropAreaBox.width) {
		cropResizeEdges.gripRight = true;
	}
	else {
		cropResizeEdges.gripRight = false;
	}

	if(y - Number(obj.getAttribute('resizeGripSize')) <= cropAreaBox.y && y + Number(obj.getAttribute('resizeGripSize')) >= cropAreaBox.y) {
		cropResizeEdges.gripTop = true;
	}
	else {
		cropResizeEdges.gripTop = false;
	}
	
	if(y - Number(obj.getAttribute('resizeGripSize')) <= cropAreaBox.y + cropAreaBox.height && y + Number(obj.getAttribute('resizeGripSize')) >= cropAreaBox.y + cropAreaBox.height) {
		cropResizeEdges.gripBottom = true;
	}
	else {
		cropResizeEdges.gripBottom = false;
	}

	if(force && oldCropResizeEdges && !(cropResizeEdges.gripLeft || cropResizeEdges.gripRight || cropResizeEdges.gripTop || cropResizeEdges.gripBottom)) {
	
		cropResizeEdges = oldCropResizeEdges;
	}
	else {
	
		oldCropResizeEdges = cropResizeEdges;
	}
}
