/**
 * @author Sergey Chikuyonok (gonarch@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru) 
 */

vtb24.calculator=function(){
	this._calc_id='calculator';
	this._calc_result_id='calculator-result';
	
	/* some constants */
	this.MIN=1;
	this.MAX=2;
	this.DAYS_IN_YEAR=365;
	this.DAYS_IN_MONTH = 30.5;
	this.MONTHS_PER_YEAR=12;
	this.EMPTY_RESULT='&#151;';
	
	this.init();
}

vtb24.calculator._id_counter=0;

vtb24.calculator.makeId=function(){
	return 'calc_elem'+(vtb24.calculator._id_counter++);
}
 
/**
 * Initiate calculator
 */
vtb24.calculator.prototype.init=function(){
	this._init_controls();
	this._init_result();
}

/**
 * Initiate observers for calculator controls
 */
vtb24.calculator.prototype._init_controls=function(){
	this.controls={};
	var parent=document.getElementById(this._calc_id);
	var control_elems=['input', 'select', 'textarea'];
	
	var items, jl;
	for(var i=0; i<control_elems.length; i++){
		items=parent.getElementsByTagName(control_elems[i]);
		jl=items.length;
		for(var j=0; j<jl; j++){
			this.addControl(items[j]);
			this.addWatch(items[j]);
		}
	}
}

/**
 * Initiate results section
 */
vtb24.calculator.prototype._init_result=function(){
	this.result={};
	var parent=document.getElementById(this._calc_result_id);
	var items=parent.getElementsByTagName('span');
	var re=/result-([\w\-]+)/;
	var c, m;
	for(var i=0; i<items.length; i++){
		c=items[i].className;
		if(c && (m=re.exec(c))){
			this.result[m[1]]=items[i];
		}
	}
}

/**
 * Adds element to controls container for faster access
 * @param {Element} elem Calculator control
 */
vtb24.calculator.prototype.addControl=function(elem){
	if(!elem.name)
		elem.name=vtb24.calculator.makeId();
	
	var name=elem.name;
	
	if(elem.nodeName == 'INPUT' && Common.Class.match(elem, 'calc-field')){
		elem=vtb24.calculator_field.get(elem.id);
	}
	
	if(this.controls[name]){
		//control already exits. convert container to array
		if(!(this.controls[name] instanceof Array)){
			var a=[];
			a[0]=this.controls[name];
			this.controls[name]=a;
		}
		this.controls[name].push(elem);
	}
	else
		this.controls[name]=elem;
}

/**
 * Returns calculator control pointer by name
 * @param {String} name Control name
 * @return {vtb24.calculator_field, Element}
 */
vtb24.calculator.prototype.getControl=function(name){
	return this.controls[name];
}

/**
 * Add watching event to be initiated when value changed in control
 * @param {Element} elem Calculator control
 */
vtb24.calculator.prototype.addWatch=function(elem){
	var me=this;
	var f=function(evt){me.calculate(evt);};

	switch(elem.nodeName){
		case 'INPUT':
			switch(elem.type){
				case 'text':
					if(Common.Class.match(elem, 'calc-field')){
						/*
						 * this item was marked as 'calculator field' and use vtb24.calculator_field class,
						 * so we need to add watcher to class instance
						 */
						var cf=vtb24.calculator_field.get(elem.id);
						if(cf)
							cf.callback=f;
						else
							Common.Event.add(elem, 'keyup', f);
					}
					else{
						Common.Event.add(elem, 'keyup', f);
					}
					break;
				case 'radio':
				case 'checkbox':
					Common.Event.add(elem, 'click', f);
					break;
			}
			break;
		case 'SELECT':
			Common.Event.add(elem, 'change', f);
			break;
	}
}

/**
 * Main calculating method
 * @param {Event} evt
 */
vtb24.calculator.prototype.calculate=function(evt){
	return;
}

/**
 * Returns control value
 * @param {String} name Control name
 * @param {Boolean} [no_convert] Don't convert value to number 
 * @return {Number, String}
 */
vtb24.calculator.prototype.getControlValue=function(name, no_convert){
	var control=this.getControl(name);
	var value=null;
	if(control){
		if(control instanceof Array){
			for(var i=0; i<control.length; i++){
				if(control[i].checked){
					value=control[i].value;
					break;
				}
			}
		}
		else{
			if(control.type == 'checkbox')
				return control.checked;
			else
				value = (control.getValue) ? control.getValue() : control.value;
		}
		
		if(!no_convert)
			value=parseInt(value);
		return value;
	}
	return null;
}

/**
 * Returns name of calculator control which fired event 
 * @param {Object} evt
 * @return {String}
 */
vtb24.calculator.prototype.getCurrentControl=function(evt){
	if(evt && (evt instanceof vtb24.calculator_field))
			return evt.id;
	else
		evt=Common.Event.check(evt);
	if(evt && evt.target)
		return evt.target.name;
	
	return null;
}

/**
 * Writes result
 * @param {String} name Name of result section
 * @param {Object} value Result to write
 */
vtb24.calculator.prototype.writeResult=function(name, value){
	if(this.result[name])
		this.result[name].innerHTML=value;
}

/**
 * Returns value from 'data' which label corresponds to 'label'
 * @param {Array} data Array of 'calculator_structure.value' objects
 * @param {Number} label
 */
vtb24.calculator.prototype.getRangedValue=function(data, label){
	var ix=this.getRangedIndex(data, label);
	//console.log('index',ix);
	return (ix != -1) ? data[ix].getValue() : null;
}

/**
 * Returns index of value value from 'data' which label corresponds to 'label'
 * @param {Array} data Array of 'calculator_structure.value' objects
 * @param {Number} label
 */
vtb24.calculator.prototype.getRangedIndex=function(data, label){
	switch(data.length){
		case 0:
			return -1;
			break;
		case 1:
			return 0;
			break;
		default:
			if(label <= data[0].getLabel())
				return 0;
				
			var prev_value=data[0].getLabel(), v;
			for(var i = 1; i < data.length - 1; i++){
				v=data[i].getLabel();
				if(label > prev_value && label <= v){
					return i;
				}
				prev_value = v;
			}
			
			return data.length - 1;
	}
}

/**
 * Disable or enable calculator control
 * @param {String} name Control name
 * @param {Boolean} [enable] Enable control element (disable by default)
 * @param {String, Number} [default_value] Set this value after disabling control
 */
vtb24.calculator.prototype.switchControlState=function(name, enable, default_value){
	enable=enable||false;
	var control=this.getControl(name);
	if(control){
		if(control instanceof Array){
			//radio or checkbox set
			//in this case we have to switch all controls except one with 'default_value' value
			if(default_value == null && !enable)
				default_value=controls[0].value;
			var label_ids=[];
			for(var i=0; i<control.length; i++){
				if(control[i].value != default_value){
					control[i].disabled=!enable;
					label_ids.push(control[i].id);
				}
				else{
					control[i].checked=true;
				}
			}
			if(label_ids.length)
				this.switchLabelState(label_ids, enable);
		}
		else if(control instanceof vtb24.calculator_field){
			
			//not implemented yet
			if(default_value != null)
				control.setValue(default_value);
		}
		else{
			//simple input element
			control.disabled=!enable;
			if(default_value != null)
				control.value=default_value;
			if(control.id)
				this.switchLabelState(control.id, enable);
		}
	}
}

/**
 * Disable of enable labels for calculator controls
 * @param {String, Array} control_id Calculator controls id
 * @param {Boolean} [enable] Enable label (disable by default)
 */
vtb24.calculator.prototype.switchLabelState=function(control_id, enable){
	enable=enable||false;
	if(!(control_id instanceof Array)){
		control_id=[control_id];
	}
	
	var items=document.getElementsByTagName('label');
	if(enable){
		for(var i=0; i<items.length; i++){
			if(control_id.contains(items[i].htmlFor) != -1)
				Common.Class.remove(items[i], 'disabled');
		}
	}
	else{
		for(var i=0; i<items.length; i++){
			if(control_id.contains(items[i].htmlFor) != -1)
				Common.Class.add(items[i], 'disabled');
		}
	}
}