// "child elements" for the Control class

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

	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_horizontalLine.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=(attributes.W?attributes.W:mm2px(this.attributes.Wmm));
	this.attributes.H=(attributes.H?attributes.H:mm2px(this.attributes.Hmm));

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

	this.attributes.fixed=(attributes.fixed?attributes.fixed:this.defaults.fixed);
	this.attributes.block=(attributes.block?attributes.block:this.defaults.block);
	this.attributes.repeatable=(attributes.repeatable?attributes.repeatable:this.defaults.repeatable);


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


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



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

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

	this.attributes.padding_top=(attributes.padding_top?attributes.padding_top:this.defaults.padding_top);
	this.attributes.padding_bottom=(attributes.padding_bottom?attributes.padding_bottom:this.defaults.padding_bottom);
	this.attributes.padding_left=(attributes.padding_left?attributes.padding_left:this.defaults.padding_left);
	this.attributes.padding_right=(attributes.padding_right?attributes.padding_right:this.defaults.padding_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_horizontalLine.prototype.create=function (){
	if(this.preview==null)
		this.preview= CloneTemplates['_control_horizontalLine'].createClone(this.parent.page);

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

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

	// there are 2 div's as parent-child relationship. Try to extract the inner child now.
	var childs=this.object.childElements();
	this.objectChild=childs[0];

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

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

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

	var childs=this.object.childElements();
	this.objectChild=childs[0];

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

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

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

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

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



_control_horizontalLine.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_horizontalLine.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_horizontalLine.prototype.getDescription=function (){
	return "line "+this.attributes.Wmm+'x'+this.attributes.Hmm+"mm";
}

// - 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_horizontalLine.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.X=mm2px(value);
			this.attributes.Xmm=value;
		break;
		case 'Ymm':
			this.attributes.Y=mm2px(value);
			this.attributes.Ymm=value;
		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 'orderIndex':
			value=parseInt(value);
			if(isNaN(value))value=0;

			var newOrder=smartPlaceElement(this,value,this.attributes.orderIndex,this.parent.staticPage,true);

			if(newOrder!=$F(this.controls['orderIndex']))this.controls['orderIndex'].value=newOrder;	// update the input value if needed.

			this.attributes.orderIndex=newOrder;

			disableUpdate=true;
		break;

		case 'block':
			this.attributes.block=(value==null?false:true);
		break;
		case 'fixed':
			this.attributes.fixed=(value==null?false:true);

			if(this.attributes.fixed){
				this.attributes.Xmm=0;
				this.attributes.Ymm=0;
				this.attributes.X=0;
				this.attributes.Y=0;

				disableElement(this.controls.Xmm,true);
				disableElement(this.controls.Ymm,true);

				this.attributes.layer=2;

				disableElement(this.controls.layer,true);

				this.parent.staticPage.appendChild(this.preview);
			}else{
				disableElement(this.controls.Xmm,false);
				disableElement(this.controls.Ymm,false);

				disableElement(this.controls.layer,false);

				this.parent.page.appendChild(this.preview);
			}

			this.parent._updateAttribtues({	Xmm:this.attributes.Xmm,
											Ymm:this.attributes.Ymm,
											X:this.attributes.X,
											Y:this.attributes.Y,
											layer:this.attributes.layer
										},this.controls);
		break;
		case 'repeatable':
			this.attributes.repeatable=(value==null?false:true);
			this.hidden=($F('repeatable_edit_')? !this.attributes.repeatable: this.attributes.repeatable) ;
		break;

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


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


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

		case 'color':
			this.attributes[attribute]=(value);

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

		case 'padding_top':
		case 'padding_bottom':
		case 'padding_left':
		case 'padding_right':
			this.attributes[attribute]=value;
		break;

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

		default:
		break;
	}

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

	return true;
}

_control_horizontalLine.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 styleChild={};
	var previewStyle={};

	var x=Math.round(this.attributes.H*Controls.getGlobal('zoom'));
	x=(x>0?x:1);
	styleChild.borderTop=x+'px '+this.attributes.style+' '+this.attributes.color;

	style.width=(this.attributes.Wmm>0?mm2px(this.attributes.Wmm):1)+'px';
	style.height=(this.attributes.Hmm>0?mm2px(this.attributes.Hmm):1)+'px';
	styleChild.width=(this.attributes.Wmm>0?mm2px(this.attributes.Wmm):1)+'px';

	// styleChild.width=(this.attributes.Wmm>0?mm2px(this.attributes.Wm):1)+'px';

	style.marginTop= 	mm2px(this.attributes.padding_top)+'px';
	style.marginBottom= mm2px(this.attributes.padding_bottom)+'px';
	style.marginLeft= 	mm2px(this.attributes.padding_left)+'px';
	style.marginRight= 	mm2px(this.attributes.padding_right)+'px';

	previewStyle.display= (this.attributes.fixed?'block':'inline');
	previewStyle.position=(this.attributes.fixed?'static':'absolute');

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

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

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


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

	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_horizontalLine.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_horizontalLine.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_horizontalLine.prototype.startDrag=function (realDragging){
	if(realDragging){
		this.parent.eventScheduler.schedule('child.onDrag',this.onDrag.bind(this),0.1);
	}
}

// endDrag :
_control_horizontalLine.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_horizontalLine.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_horizontalLine.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_horizontalLine']=new _cloneFactory(
											'_control_horizontalLine_.:id:.',
											{
												'id':	{	type:'int',	start:'1'	}
											},
											{
												bulkEval:true
											}
										);

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