// "child elements" for the Control class

// the IMAGE control.
// define events, attributes, and methods to handle a "image control"
function _control_image( parent ){// constructor for the main class
	if(this.name==null || !this.name )	{
		this.name='_control_image';
	}

	this.parent=parent;
	this.version='1.0.0.0';
	this._heap=new Array();
	this.attributes={};
	this.defaultAttributes={};
	this.controls={};

	this.autoApplyUpdateDelay=0.25;

	this.defaults=this.getDefaults();
}

// initialize the control with "default" pre-specified values
_control_image.prototype.initialize=function (attributes){
	if(attributes==null)attributes={};
	var defX=px2mm($('pageContainer').scrollLeft);
	var defY=px2mm($('pageContainer').scrollTop);

	/////////////// OBJECT POSITION AND DIMENSIONS ////////////////////////////
	this.attributes.Xmm=(attributes.Xmm?attributes.Xmm:defX);
	this.attributes.Ymm=(attributes.Ymm?attributes.Ymm:defY);
	this.attributes.X=mm2px(this.attributes.Xmm);
	this.attributes.Y=mm2px(this.attributes.Xmm);

	this.attributes.Wmm=(attributes.Wmm?attributes.Wmm:this.defaults.Wmm);
	this.attributes.Hmm=(attributes.Hmm?attributes.Hmm:this.defaults.Hmm);
	this.attributes.W=mm2px(this.attributes.Wmm);
	this.attributes.H=mm2px(this.attributes.Hmm);

	this.attributes.URL=(attributes.URL?attributes.URL:this.defaults.URL);


	this.attributes.repeatable=(attributes.repeatable?attributes.repeatable:this.defaults.repeatable);
	this.attributes.layer=(attributes.layer?attributes.layer:'2');

	/////////////// MISC ATTRIBUTES ////////////////////////////////////////////
	this.attributes.conditionalVisibility=(attributes.conditionalVisibility?attributes.conditionalVisibility:this.defaults.conditionalVisibility);

	this.attributes.src=(attributes.src?attributes.src:this.defaults.src);

	this.attributes.scaleX=(attributes.scaleX?attributes.scaleX:this.defaults.scaleX);
	this.attributes.scaleY=(attributes.scaleY?attributes.scaleY:this.defaults.scaleY);


	/////////////// COLORS AND SPACING /////////////////////////////////////////
	this.attributes.opacity=(attributes.opacity?attributes.opacity:this.defaults.opacity);
	this.attributes.borderColor=(attributes.borderColor?attributes.borderColor:this.defaults.borderColor);

	this.attributes.border_top=(attributes.border_top?attributes.border_top:this.defaults.border_top);
	this.attributes.border_bottom=(attributes.border_bottom?attributes.border_bottom:this.defaults.border_bottom);
	this.attributes.border_left=(attributes.border_left?attributes.border_left:this.defaults.border_left);
	this.attributes.border_right=(attributes.border_right?attributes.border_right:this.defaults.border_right);

	this.attributes.assignedGroup=(attributes.assignedGroup?attributes.assignedGroup:this.defaults.assignedGroup);

	// save the default attrbiutes, so they may get re-used
	//  when invalid propreties are met, and we need to do some kind of rollback
	this.defaultAttributes=Object.clone(this.attributes);

	return true;
}

// create the control, the attributeSelector, and attach them to the DOM
_control_image.prototype.create=function (){
		if(this.preview==null)
		this.preview= CloneTemplates['_control_image'].createClone(this.parent.page);

	if(this.object==null)
		this.object= $(this.preview).select("[id='object']").first();

	if(this.attributesSelector==null)
		this.attributesSelector = CloneTemplates['_control_image_attributes'].createClone(this.parent.attributesContainer);

	// standard initializing
	this.controls=this.getAttributesControls();
	this.fillAttributes();

	// get the dimensions, and save them
	this.getDimensions();

	var elements=$(this.attributesSelector).select("[id='objectStatus']");
	this.statusBox=$(elements[0]);
}

// FAST create the control, the attributeSelector, and attach them to the DOM
_control_image.prototype.fastCreate=function (){
	if(this.object==null)
		this.object= $(this.preview).select("[id='object']").first();

	// standard initializing
	this.controls=this.getAttributesControls();
	this.fillAttributes();

	// get the dimensions, and save them
	this.getDimensions();

	var elements=$(this.attributesSelector).select("[id='objectStatus']");

	this._heap['reloadImageInfo']=true;

	this.parent.status({status:'idle',percent:1});

	this.statusBox=$(elements[0]);
}

_control_image.prototype.destroy=function (){
	this._heap=null;
	this.attributes=null;

	if(this.preview)
		$(this.preview).remove();

	if(this.attributesSelector)
		$(this.attributesSelector).remove();

	this.preview=null;
	this.object=null;
	this.attributesSelector=null;
	this.defaultAttributes=null;
	this.parent=null;
	this.controls=null;
}

_control_image.prototype.getDimensions=function (){
	// calculate the object dimensions. we do a caclulation hare, and another in the onChange event
	this.objectDimensions=Element.getDimensions(this.object);
	return this.objectDimensions;
}

// used by "group" controls, to display a short description of this control
_control_image.prototype.getDescription=function (){
	var src='';
	var matches=String(this.attributes.src).match(/(\/)([a-z\-\_\.]+)$/i);
	if(matches)
		src=matches[2];

	return "image '"+src+"'";
}

// - an attribute has changed, reflect this in the internal data, and in the viewed item
// - some attributes are checked separately, when needing to do extra validation,
//     or the input data is non-standard (for example when $F cannot handle it)
_control_image.prototype.onChange=function (event,attribute,disableUpdate){
	if(attribute==null) return;
	var disableUpdate=false;

	var element=this.controls[attribute];
	var initialValue=this.attributes[attribute];

	value=$F(element);

	switch(attribute){
		/////////////// OBJECT POSITION AND DIMENSIONS ////////////////////////////
		case 'Xmm':
			this.attributes.Xmm=Number(value);
			this.attributes.X=mm2px(this.attributes.Xmm);
		break;
		case 'Ymm':
			this.attributes.Ymm=Number(value);
			this.attributes.Y=mm2px(this.attributes.Ymm);

			// add new pages to this document if needed
		    if(this.attributes.Y>=(grid._heap['pageH']*grid._heap['pages'])){
				grid.expandPageRange(this.attributes.X,this.attributes.Y);
		    }
		break;

		case 'Wmm':
			this.attributes.Wmm=value;
			this.attributes.W=mm2px(value);
		break;
		case 'Hmm':
			this.attributes.Hmm=value;
			this.attributes.H=mm2px(value);
		break;
		case 'repeatable':
			this.attributes.repeatable=(value==null?false:true);
			this.hidden=($F('repeatable_edit_')? !this.attributes.repeatable: this.attributes.repeatable) ;
			this.updateObject();
			disableUpdate=true;
		break;

		case 'layer':
			this.attributes.layer=value;
		break;

		/////////////// MISC ATTRIBUTES ////////////////////////////////////////////
		case 'conditionalVisibility':
			this.attributes[attribute]=value;
		break;

		case 'src':
			if(this.statusBox);
				$(this.statusBox).update('');

			this.attributes.src=(value?value:this.defaultAttributes.src);

			if(this.statusBox){
				new Ajax.Request('getFile.php?get=imageInfo&path='+this.attributes.src,
						{
							onSuccess: function(transport, json) {
								$(this.statusBox).update(transport.responseText);

								if(this.attributes.Wmm==0 && json.width){
									this.attributes.Wmm=json.width;
									this.attributes.W=mm2px(json.width);
								}

								if(this.attributes.Hmm==0 && json.height){
									this.attributes.Hmm=json.height;
									this.attributes.H=mm2px(json.height);
								}

								this.fillAttributes();
							}.bind(this)
						});
			}
		break;

		case 'scaleX':
			this.attributes.scaleX=value;
		break;
		case 'scaleY':
			this.attributes.scaleY=value;
		break;

		case 'assignedGroup':
			this.attributes.assignedGroup=value;
		break;

		case 'URL':
			this.attributes.URL=value;
		break;

		/////////////// COLORS AND SPACING /////////////////////////////////////////
		case 'opacity':
			this.attributes.opacity=Math.max(0,Math.min(value,100));
		break;

		case 'borderColor':
			this.attributes[attribute]=value;

			setPreviewBackgroundColor(this.attributesSelector,attribute,this.attributes[attribute]);
		break;

		case 'border_top':
		case 'border_bottom':
		case 'border_left':
		case 'border_right':
			this.attributes[attribute]=(value==null?false:true);

			var attr=String(attribute).replace('border_','');
			var input=$$("#"+this.attributesSelector.identify()+" input[id='"+attribute+"']");
			input=input[0];

			setPreviewBorder($(input).up('table'),attr,this.attributes[attribute]);
		break;


		default:
		break;
	}

	if(!disableUpdate){
		this.updateObject();
		this.parent.reposition({Xmm:this.attributes.Xmm, Ymm:this.attributes.Ymm});
	}

	return true;
}

_control_image.prototype.updateObject=function (realCall,updateGrid){
	if(realCall!=true){
		this.parent.eventScheduler.schedule('updateObject',this.updateObject.bind(this,true,updateGrid),this.autoApplyUpdateDelay);
		return false;
	}

	var style={};
	var previewStyle={};

	if(this.attributes.Wmm>0 && this.attributes.Hmm>0){
		var x=Math.round(mm2px(this.attributes.Wmm)*this.attributes.scaleX/100);
		style.width=x+'px';

		var x=Math.round(mm2px(this.attributes.Hmm)*this.attributes.scaleY/100);
		style.height=x+'px';
	}

	style.opacity='transparent';
	if(this.attributes.opacity!='')style.opacity=this.attributes.opacity/100;


	style.borderStyle='solid';
	style.borderWidth='1px';
	if(this.attributes.borderColor)style.borderColor=this.attributes.borderColor;

	style.borderTopWidth=(this.attributes.border_top?'1px':'0');
	style.borderBottomWidth=(this.attributes.border_bottom?'1px':'0');
	style.borderLeftWidth=(this.attributes.border_left?'1px':'0');
	style.borderRightWidth=(this.attributes.border_right?'1px':'0');

	previewStyle.zIndex=parseInt(this.attributes.layer)+100;

	if(this.attributes.assignedGroup) {
		previewStyle.border = '1px dashed #008';
	}else {
		previewStyle.border = '';
	}


	this.object.setStyle(style);
	this.preview.setStyle(previewStyle);

	if(this.attributes.src)
		this.object.src='getFile.php?get=highlightedImage&path='+this.attributes.src;
		//this.object.src='getFile.php?get=image&path='+this.attributes.src;
	else
		this.object.src='_img/objects/image/image.jpg';

	this.getDimensions();

	if(this.hidden){
		this.preview.hide();
		this.hidden=false;
	}else{
		this.preview.show();
	}
	this.parent.status({status:'idle',percent:1});
}

// return the internal attributes(you should rely on this, instead of the attributes in the attributesSelector!. They are keeped in sync anyway)
_control_image.prototype.getAttributes=function (){
	if(this.object==null) return false;
	return this.attributes;
}

// return a list of attribute controls (the actual inputs). Internally used to sync with the internal attributes list
_control_image.prototype.getAttributesControls=function (){
	var a;
	var elements;
	var subElement;
	var ret={};

	var attributes=this.getAttributes();
	var attributesSelector=this.attributesSelector;

	for(var i in attributes){
		a="[id='"+i+"']";
		elements=$(attributesSelector).select(a);

		if(elements){
			for(var j=0;j<elements.length;j++){
				subElement=elements[j];
				ret[i]=subElement;
			}
		}
	}

	return ret;
}

// startDrag:
_control_image.prototype.startDrag=function (realDragging){
	if(realDragging){
		this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this),0.1);
	}else{
		if(this._heap['reloadImageInfo']){
			new Ajax.Request('getFile.php?get=imageInfo&path='+this.attributes.src,
							{
								onSuccess: function(transport,json) {
									$(this.statusBox).update(transport.responseText);

									if(this.attributes.Wmm==0 && json.width){
										this.attributes.Wmm=json.width;
										this.attributes.W=mm2px(json.width);
									}

									if(this.attributes.Hmm==0 && json.height){
										this.attributes.Hmm=json.height;
										this.attributes.H=mm2px(json.height);
									}

									this.fillAttributes();
								}.bind(this)
							});
		}
	}
}

// endDrag :
_control_image.prototype.endDrag=function (realDragging){
	if(!realDragging){
		this.parent.eventScheduler.cancel('child.onDrag');
	}else{
		this._heap['onDrag_timed']=null;
		this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this,'deccelerate'),1);
	}
}

_control_image.prototype.onDrag=function (delay){
	if(this.parent._heap['x']!=null && this.parent._heap['y']!=null){
		if(this.parent._heap['Xmm'] && this.parent._heap['Ymm']){
			this.attributes.Xmm=this.parent._heap['Xmm'];
			this.attributes.Ymm=this.parent._heap['Ymm'];
		}else{
			this.attributes.Xmm=px2mm(this.parent._heap['x'],true,2);
			this.attributes.Ymm=px2mm(this.parent._heap['y'],true,2);
		}

		this.attributes.X=this.parent._heap['x'];
		this.attributes.Y=this.parent._heap['y'];

		var fillResponse=this.fillAttributes({Xmm:this.attributes.Xmm,Ymm:this.attributes.Ymm});
	}

	switch(delay){
		case 'deccelerate':
			this._heap['onDrag_timed']=(this._heap['onDrag_timed']?this._heap['onDrag_timed']:1);
			if(fillResponse && fillResponse.changed){
				this._heap['onDrag_timed']=Math.round(this._heap['onDrag_timed']*0.75);
			}else{
				// prevent this event from reoccuring
				break;
			}

			this._heap['onDrag_timed']=Math.max(this._heap['onDrag_timed'],0.25);
			this._heap['onDrag_timed']=Math.min(this._heap['onDrag_timed'],60);
			this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this,'deccelerate'),this._heap['onDrag_timed']);
		break;
		case 'slow':
			this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this,'slow'),2.5);
		break;
		default:
			this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this),0.5);
		break;
	}
}

// sync the attributesSelector with the internal attributes (overwrite them)
_control_image.prototype.fillAttributes=function (attr){
	var controls=this.controls;
	var attributes=(attr?attr:this.attributes);
	var changed=false;

	changed=this.parent._updateAttribtues(attributes,controls);

	return {attributes:attributes,changed:changed};
}

///////////////////////////////////////////////////////////////////////////////////
// standard initalization for this class, performed on pageLoad ///////////////////

Event.observe(window, 'load', function() {
	CloneTemplates['_control_image']=new _cloneFactory(
											'_control_image_.:id:.',
											{
												'id':	{	type:'int',	start:'1'	}
											}
										);

	CloneTemplates['_control_image_attributes']=new _cloneFactory(
											'_control_image_.:id:._attributes',
											{
												'id':	{	type:'int',	start:'1'	}
											},
											{
												bulkEval:true
											}
										);
});