/*********************************************************************************/
/**			copyright (c) PlanetCalc.com, 2009-2010			**/
/**		    	Planet Calc formatting functions			 */
/*********************************************************************************/

var PCF = function () {	//planet calc formatting functions
	var precision;
	var precisionControls=[];
	var precisionHandlers =[];

	function foreachPrecisionLink( elem, func ) {
			if ( !elem.childNodes ) {
				return;
			}
			var namePrefix = "precision";
			for (var childItem in elem.childNodes) {
				var child = elem.childNodes[childItem];
				if (child.nodeType == 1 ){
					if ( child.name && child.name.substr(0,namePrefix.length)==namePrefix ) {
						var index =child.name.substr(namePrefix.length);
						func( child, index );	
					} else {
						foreachPrecisionLink( child, func );
					}
				}
			}

	}
	return {
		"advisePrecisionmeter": function( elem, decimals, handler ) {
			if ( typeof(precision)=='undefined' ) {
				precision = decimals;
			}
			precisionControls[precisionControls.length] = elem;
			precisionHandlers[precisionHandlers.length] = handler;
			foreachPrecisionLink( elem, function ( child, index ) { BSAdviseEvent( child, "click", PCF.changeCalcPrecision, index ) } );
			foreachPrecisionLink( elem, function ( child, index ) { if (index!="Plus" && index!="Minus" ) { var nIndex = Number( index); child.className = nIndex<=decimals?"selected":""; } } );
		},
		"getMaxPrecision": function ( ) {
			return 20;
		},
		"getCalcPrecision": function ( ) {
			return precision;
		},
		"setCalcPrecision": function ( p ) {
			precision = p;
		},
		"changeCalcPrecision": function ( ps ) {
			var p = Number(precision);
			if (ps=="Plus" ) {
				if ( p<PCF.getMaxPrecision() ) p+=1;
			} else if (ps=="Minus") {
				if( p>0 ) p-=1;
			} else {
				p = Number(ps);
			}
			precision = p;
			for( var i=0;i<precisionControls.length;++i ) {
				var elem = precisionControls[i];
				var handler = eval(precisionHandlers[i]);
				foreachPrecisionLink( elem, function ( child, index ) { if (index!="Plus" && index!="Minus" ) { var nIndex = Number( index); child.className = nIndex<=precision?"selected":""; } } );
				handler.onchanged( "precisionmeter" );
			}
		}
	}
}();

function GetDateParts( d , index ) {
	var parts = [d.getFullYear(), d.getMonth()+1,  d.getDate(), d.getHours(), d.getMinutes(), 
			d.getSeconds(), d.getMilliseconds() ];
	var maximums = [ 0,12,31,23,60,60,1000 ];
	for( var i=maximums.length-1;i<index && i>0;++i ) {
		var current = parts[i];
		if ( current>=maximums[i]/2 ) {
			parts[i-1]+=1;
			if ( index==i+1 ) {
				--index;
			}
		}
	}
	d = new Date( parts[0],parts[1]-1,parts[2],parts[3],parts[4],parts[5],parts[6] );
	return [d.getFullYear(), d.getMonth()+1,  d.getDate(), d.getHours(), d.getMinutes(), 
			d.getSeconds(), d.getMilliseconds() ];
}
function FormatDate( format, value ) {
	if ( value == "0000-00-00 00:00:00" || !value )	{
		return "";
	}
	var d = typeof(value)=='string'?String2Date(value):new Date(value);
	var roundingIndex = 6; //round up to milliseconds;
	if ( format.search("%8")==-1 ) {
		roundingIndex = 4;
	} else if ( format.search("%9")==-1 ) {
		roundingIndex = 5;
	}
	var parts = GetDateParts( d, roundingIndex );
	var bc = parts[0]<=0?(' ' + getFormattedMessage('b_c')):'';
	if ( parts[0]<0 ) {
		parts[0] = 1-parts[0];
	}

	var century = Math.ceil( d.getFullYear()/100 ) + ' ' + getFormattedMessage('century') + bc;
	return formatMessage(format,leftpad(parts[0],'0',4),leftpad(parts[1],'0',2),leftpad(parts[2],'0',2), bc, century, leftpad(parts[3],'0',2), leftpad(parts[4],'0',2), leftpad(parts[5],'0',2), leftpad(parts[6],'0',3));

}

function FormatAbsDegrees( nVal ) {
	if ( nVal<0 ) nVal = -nVal;
	var res = Math.floor( nVal ) + '&#176;';
	var rem = Math.round((nVal-Math.floor( nVal ))*3600);
	if ( rem ) {
		res = res + Math.floor(rem/60) + "'";
		if ( rem%60 ) {
			res = res + (rem%60) + '"';
		}
	}
	return res;
}

function FormatterDegrees( ) {
	this.Format = function ( value ) {
		var nVal = Number(value);
		var sign = nVal<0?"-":"";
		return sign+FormatAbsDegrees( nVal );
		
	}
}

function FormatterCoordinate( kind ) {
	var stringIds = kind=='lat'?['latitudeN','latitudeS']:['longitudeE','longitudeW']
	this.Format = function ( value ) {
		var nVal = Number(value);
		var s = getFormattedMessage(stringIds[ nVal<0?1:0]);
		return FormatAbsDegrees( nVal ) + ' ' + s;
		
	}
}

function FormatterDate() {
	this.Format = function ( value ) {
		return FormatDate('date_format',value);
	}
}
function FormatterBoolean() {
	this.Format = function ( value ) {
		return getFormattedMessage( value?'yes':'no');
	}
}



function FormatterDateFlags( flags ) {
	var dateFormat = getFormattedMessage( 'date_format');
	var dateTimeFormat = getFormattedMessage( 'date_time_format');
	var formats = [ '', dateFormat, '%6:%7',
		dateTimeFormat, '%5', '%5 ' + dateFormat, '%5 %6:%7', '%5 ' + dateTimeFormat];
	this.Format = function ( value ) {
		return FormatDate(formats[flags],value);
	}
}


function FormatterImage(titlevalue) {
	var title = titlevalue;
	this.Format = function ( value ) {
		if (value != "")
			return '<img src="' + value + '" alt="' + title + '" title="'+ title + '"/>';
		return "";
	}
}

function FormatterFormula() {
	this.Format = function ( value ) {
		if (value != "")
			return '<img src="/cgi-bin/mimetex.cgi?' + value + '" alt=""/>';
		return "";
	}
}



function FormatterSimpleURL() {
	this.Format = function ( value ) {
		if (value != "") {
			var link = value;
			if (link.substr(0,4) != "http")
				link = "http://" + link;
			return '<a href="' + link + '" />' + value + '</a>';
		}
		return "";
	}
}

function FormatterDateOnly() {
	this.Format = function ( value ) {
		if ( value == "0000-00-00 00:00:00" || !value )	{
			return "";
		} else {
			var dateObj = String2Date( value );
			var mils = dateObj.getTime();
			mils -= 1000*60*dateObj.getTimezoneOffset();
			dateObj.setTime(mils);                                        
			return dateObj.getFullYear() + "." + ((dateObj.getMonth()+1) < 10 ? "0" + (dateObj.getMonth()+1) : (dateObj.getMonth()+1)) + "." + dateObj.getDate();
		}                                  
	}
}

function FormatterTimeSpan() {
	this.Format = function ( value ) {
		if ( value== "0000-00-00 00:00:00" || !value ) {
			return "";
		} else {
			var dateObj = String2Date( value );
			var mils = dateObj.getTime();
			mils -= 1000*60*dateObj.getTimezoneOffset();
			dateObj.setTime(mils);
			var recordms = dateObj.getTime();
			var nowms = new Date().getTime();
			return ComputeSpan(nowms - recordms);
		}                                  
	}

	function ComputeSpan(mils) {
		if (mils < 60 * 60*1000) //below hour
			return FetchLabel("minute_", mils / (60*1000));
		else if (mils < 24 * 60*60*1000) //below day
			return FetchLabel ("hour_", mils / (60*60*1000));
		else if (mils < 31 * 24*60*60*1000) //below 31 day
			return FetchLabel ("day_", mils / (24*60*60*1000));
		else if (mils < 12 * 31*24*60*60*1000) //below 12 month
			return FetchLabel ("month_", mils / (31*24*60*60*1000));
		else 
			return FetchLabel ("year_", mils / (12*31*24*60*60*1000) );
	}
	
	function FetchLabel(prefix, span) {
		var span = Number(span).toFixed(0);
		var tail = span;
		if (span >= 10 && span <= 20)
			return span + " " + getFormattedMessage(prefix + "1X") + " " + getFormattedMessage("ago");
		else if (span > 20) 
			tail = span % 10;

		return span + " " + getFormattedMessage(prefix + tail.toString()) + " " + getFormattedMessage("ago");
	}
}

function FormatterMap( args ) {
	var m_labels = new Array();
	for( var i = 0;i<args.length;i+=2 ) {
		m_labels[args[i]] = args[i+1];
	}	
	this.Format = function ( value ) {
		var res = m_labels[ value ];
		return typeof(res)=='undefined'?'':res;
	}
}

function DoubleFormatterMap( args ) {
	var m_labels = new Array();
	for( var i = 0;i<args.length;i+=2 ) {
		m_labels[args[i]] = args[i+1];
	}	

	this.Formatter = new FormatterSame();

	this.Format = function ( value ) {
		var res = m_labels[ value ];
		return typeof(res) == 'undefined' ? '' : this.Formatter.Format(res);
	}
}

function FormatterLabel( label ) {
	this.Format = function ( value ) {
		return label;
	}
}

function FormatterPrefix( prefix, formatter ) {
	var optionalFormatter = formatter;
	this.Format = function ( value ) {
		return prefix + (optionalFormatter != null ? optionalFormatter.Format(value) : value);
	}
}

function FormatterEmptyLabel( label ) {
	this.Format = function ( value ) {
		if ( typeof(value)=='undefined' ) {
			return label;
		}
		return value;
	}
}

function FormatterSame( ) {
	this.Format = function ( value ) {
		return value;
	}
}

function FormatterNumber( decimals ) {
	this.Format = function ( value ) {
		var numVal = new Number( value );
		var precision = decimals;
		if ( precision ) {
			precision = PCF.getCalcPrecision();
			if( typeof( precision ) == 'undefined') {
				precision = decimals;
			}
		}
		return numVal.toFixed( precision );
	}
}

function FormatterPersent( decimals ) {
	this.Format = function ( value ) {
		var persentValue = value*100;
		return persentValue.toFixed( decimals );
	}
}
