
///////////////////////////////////////////////////////////////////////
// global state
///////////////////////////////////////////////////////////////////////

/*
	Set to true to have the flash output show debug information
*/
var DebugFlashOutput = false;
var PathToConstantsXMLFile = "energycalc_constants.xml";
var AssumptionsShowing = false;

///////////////////////////////////////////////////////////////////////
// initialization
///////////////////////////////////////////////////////////////////////

/**
	This initialization function, wires events and sets everything up
*/

function initializeCalculator()
{
	var motorTypes = new Array( "gearboxes", "pumps", "compressors", "fans" );
	
	for ( i = 0; i < motorTypes.length; i++ ) 
	{
		intitializeMotorNum( $( motorTypes[i] + "_num" ), motor_states[motorTypes[i]].num );
		intitializeMotorKilowatts( $( motorTypes[i] + "_kw" ), motor_states[motorTypes[i]].kw );
		intitializeMotorEfficiency( $( motorTypes[i] + "_efficiency" ), motor_states[motorTypes[i]].efficiency );
		intitializeMotorHoursPerDay( $( motorTypes[i] + "_hours" ), motor_states[motorTypes[i]].hours );
		intitializeMotorDaysPerYear( $( motorTypes[i] + "_days" ), motor_states[motorTypes[i]].days );
	}
		
	$( "currency_type" ).onchange = function() { changeCurrency( this ); }
	
	initializeEnergyTypes( $( "energy_type" ), assumptions.energy );
	initializeEnergyCost( $( "energy_cost" ), assumptions.energy.cost );
	initializeCO2Cost( $( "co2_cost" ), assumptions.co2cost );
	
	updateCurrencyDisplay();
	updateEnergyTypeDisplay();	
	updateSavings();		
}

/**
	Initialize the energy types option box
*/
function initializeEnergyTypes( select, defaultValue )
{
	select.options.length = 0;
	
	var firstEnergyType = null;
	for ( i in energy_types )
	{
		var n = energy_types[i].name;
		var o = new Option( n, n, false, n == defaultValue );
		select.options[ select.options.length ] = o;
		
		if ( !firstEnergyType ) firstEnergyType = n;
	}
	
	if ( select.options.length > 1 )
	{
		select.onchange = function() { changeEnergyType( this ); }
		$( "default_energy_type" ).setStyle( "display", "none" );
	}
	else
	{
		select.setStyle( "display", "none" );
		changeEnergyType( select );
		
		$( "default_energy_type" ).innerHTML = firstEnergyType;
	}
}

/**
	Initialize the energy cost input box
*/
function initializeEnergyCost( input, defaultValue )
{
	input.value = (USDToCurrency( assumptions.currency, defaultValue )).toFixed(2);
	input.onblur = input.onchange = function() { changeEnergyCost( this ); }
}

/**
	Initialize the co2 input box
*/
function initializeCO2Cost( input, defaultValue )
{
	input.value = (USDToCurrency( assumptions.currency, defaultValue )).toFixed(2);
	input.onblur = input.onchange = function() { changeCO2Cost( this ); }
}

/**
	Initialize a motor number input box
*/
function intitializeMotorNum( input, defaultValue )
{
	input.value = defaultValue;
	input.onblur = input.onchange = function() { processMotorSelection( this ); }
}

/**
	Initialize a motor kW option box
*/
function intitializeMotorKilowatts( input, defaultValue )
{
	input.value = defaultValue;
	input.onblur = input.onchange = function() { processMotorSelection( this ); }
}

/**
	Initialize a motor kW option box
*/
function intitializeMotorEfficiency( input, defaultValue )
{
	input.value = defaultValue;
	input.onblur = input.onchange = function() { processMotorSelection( this ); }
}

/**
	Initialize a motor hours option box
*/
function intitializeMotorHoursPerDay( select, defaultValue )
{
	select.options.length = 0;
	for ( n = 0; n <= 24; n += 1 )
	{
		var o = new Option( n, n, false, n == defaultValue );
		select.options[ select.options.length ] = o;
	}

	select.onblur = select.onchange = function() { processMotorSelection( this ); }
}

/**
	Initialize a motor days-per-year
*/
function intitializeMotorDaysPerYear( select, defaultValue )
{
	select.options.length = 0;
	for ( n = 0; n <= 365; n += 5 )
	{
		var o = new Option( n, n, false, n == defaultValue );
		select.options[ select.options.length ] = o;
	}

	select.onblur = select.onchange = function() { processMotorSelection( this ); }
}

///////////////////////////////////////////////////////////////////////
// callbacks
///////////////////////////////////////////////////////////////////////

/**
	Callback used by all motor option boxes.
	Parses the motor type and parameter from select's id and applies to motor_state
*/
function processMotorSelection( input )
{
	// inputs are named "type"_"property"	
	var type = input.id.substring( 0, input.id.indexOf( "_" ));
	var property = input.id.substring( input.id.indexOf( "_" ) + 1, input.id.length );	
	var value = null;

	if ( input.type == "text" )
	{
		if ( property == "efficiency" )
		{
			value = floatValueOfInput( input, efficiencyValidator );
		}
		else
		{
			value = intValueOfInput( input, inputValueMustBeAtLeastZero );
		}
	}
	else if ( input.type == "select-one" )
	{	
		value = valueOfSelect( input );
	}

	if ( !isNaN(value) && (Math.abs( value - motor_states[ type ][property] ) > 0 ))
	{
		motor_states[ type ][property] = value;
		updateSavings();
	}
}

/**
	Callback for the currency selection box
	
	updates 'assumptions.currency'
	
	Re-initializes the energy cost and co2 cost option boxes to reflect currency conversions.
	Also changes all references to currency in the html <span class="currencyType">[CURRENCY]</span> to use the appropriate symbol.	
*/
function changeCurrency( select )
{
	var c = valueOfSelect( select );
	//alert( "changeCurrency: " + c );
	
	assumptions.currency = c;
	initializeEnergyCost( $( "energy_cost" ), assumptions.energy.cost );
	initializeCO2Cost( $( "co2_cost" ), assumptions.co2cost );

	updateCurrencyDisplay();	
	updateSavings();
}

/**
	Callback for the energy type selection box

	updates 'assumptions.energy'

	Re-initializes the energy cost option box
	Also changes all references to energy in the html <span class="energyType">[ENERGY]</span> to use the appropriate energy name.	
*/
function changeEnergyType( select )
{
	var e = valueOfSelect( select );
	
	for ( i in energy_types )
	{
		if ( energy_types[i].name == e ) assumptions.energy = energy_types[i];		
	}

	initializeEnergyCost( $( "energy_cost" ), assumptions.energy.cost );	
	updateEnergyTypeDisplay();		

	updateSavings();
}

/**
	callback for changing energy cost.
	updates 'assumptions.energy.cost' as us dollars
*/
function changeEnergyCost( input )
{
	var v = floatValueOfInput( input, inputValueMustBeGreaterThanZero );
	if ( !isNaN(v))
	{
		var c = CurrencyToUSD( assumptions.currency, v );
		if ( Math.abs( c - assumptions.energy.cost ) > 0.01 )
		{
			assumptions.energy.cost = c;
			updateSavings();
		}
	}
}

/**
	callback for changing energy cost.
	updates 'assumptions.co2cost'
*/
function changeCO2Cost( input )
{
	var v = floatValueOfInput( input, inputValueMustBeAtLeastZero );
	if ( !isNaN(v))
	{
		var c = CurrencyToUSD( assumptions.currency, v );
		if ( Math.abs( c - assumptions.co2cost ) > 0.01 )
		{
			assumptions.co2cost = c;
			updateSavings();
		}
	}
}

/*
	Invoked by callbacks to recalculate savings, etc.
	This will cause flash to reload with new parameters
*/

function updateSavings()
{
	injectFlashResults();
}

function injectFlashResults()
{
	var width = 719;
	var height = 127;
	var identifier = "flashResults";
	var file = "/contentcomponents/multimedia/energycalc_results.swf";
	var flashVars = flashParameters( DebugFlashOutput );
	
	var flashStr = "<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" width=\"" + width + "\" height=\"" + height + "\" id=\"" + identifier + "\" align=\"middle\">\n" + 
	               "<param name=\"allowScriptAccess\" value=\"sameDomain\" />\n" +
	               "<param name=\"movie\" value=\"" + file + "\" />\n" + 
	               "<param name=\"quality\" value=\"high\" />\n" +
	               "<param name=\"wmode\" value=\"transparent\" />\n" +
	               "<param name=\"flashvars\" value=\"" + flashVars + "\" />\n" +
	               "<embed src=\"" + file + "\" quality=\"high\" wmode=\"transparent\" width=\"" + width + "\" height=\"" + height + "\" name=\"" + identifier + "\" flashvars=\"" + flashVars + "\" align=\"middle\" allowScriptAccess=\"sameDomain\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\"/>\n" +
	               "</object>\n";

	$("results").setHTML( flashStr );	
}

function flashParameters( showParams )
{
	var motorParams = "";
	var motorNames = new Array( "gearboxes", "pumps", "compressors", "fans" );
	var paramNames = new Array( "num", "kw", "efficiency", "hours", "days" );
	
	for ( var m  = 0; m < motorNames.length; m++ )
		for ( var p = 0; p < paramNames.length; p++ )
			motorParams = motorParams + motorNames[m] + "_" + paramNames[p] + "=" + motor_states[ motorNames[m]][ paramNames[p]] + "&";
	
	return motorParams + 
		   "currency=" + assumptions.currency + "&" +
		   "conversionrate=" + conversion_rates[assumptions.currency] + "&" +
		   "energy=" + assumptions.energy.name + "&" +
		   "energycost=" + assumptions.energy.cost + "&" +
		   "co2cost=" + assumptions.co2cost + "&" +
		   "debugOverlay=" + (showParams ? "true" : "false" ) + "&" +
		   "constantsXML=" + PathToConstantsXMLFile + "&";
}

///////////////////////////////////////////////////////////////////////
// helpers
///////////////////////////////////////////////////////////////////////

/**
	Since we want the HTML page to reflect the current currency, we need to
	replace dollar signs with euro signs and whatnot. Each instance of
	currency in the HTML is wrapped with a span of class "currencyType",
	so find each and replace.
*/
function updateCurrencyDisplay()
{
	var currencySymbol = "$";
	if ( assumptions.currency == "usd" ) currencySymbol = "$";
	else if ( assumptions.currency == "euro" ) currencySymbol = "&euro;";
	else if ( assumptions.currency == "yen" ) currencySymbol = "&yen;";
	else if ( assumptions.currency == "yuan" ) currencySymbol = "&yen;";
	else if ( assumptions.currency == "pound" ) currencySymbol = "&pound;"
	else alert( "updateCurrencyDisplay: Unrecognized currency \"" + assumptions.currency + "\"" );

	$$( ".currencyType" ).each( function( c ) {
		c.setHTML( currencySymbol );
	});
}

/**
	The HTML page displays the energy type, so keep it updated.
	Energy type is displayed wrapped in a span named "energyType",
	so find each and swap out.
*/
function updateEnergyTypeDisplay()
{
	$$( ".energyType" ).each( function( s ) {
		s.setHTML( assumptions.energy.name );
	});
}

/**
	Return the value of a <select> box on the page, or
	null if no value is selected.

	param 'select' the select box in question.
*/
function valueOfSelect( select )
{
	for ( var i = 0; i < select.options.length; i++ )
	{
		if ( select.options[i].selected ) return select.options[i].value;
	}
	
	return null;
}

/**
	Attempt to parse a number from the <input type="text">.
	If it doesn't parse, 
*/
function intValueOfInput( input, testFunc )
{
	var v = parseInt( input.value );
	if ( isNaN( v ) )
	{
		inputError( input, "Please enter a number" );
		return v;	
	}
	
	if ( testFunc )
	{
		error = testFunc( v );
		if ( error )
		{
			inputError( input, error );
			return 1/0; // NaN
		}
	}

	// we're good
	clearInputError( input );
	
	return v;
}

/**
	Attempt to parse a number from the <input type="text">.
	If it doesn't parse, 
*/
function floatValueOfInput( input, testFunc )
{
	var v = parseFloat( input.value );
	if ( isNaN( v ) )
	{
		inputError( input, "Please enter a number" );
		return v;	
	}
	
	if ( testFunc )
	{
		error = testFunc( v );
		if ( error )
		{
			inputError( input, error );
			return 1/0; // NaN
		}
	}

	// we're good
	clearInputError( input );
	
	return v;
}

function inputError( input, errorMessage )
{
	if ( !input.hasClass( "error" )) input.addClass( "error" );
	$("inputError").setHTML( errorMessage );
}

function clearInputError( input )
{
	$("inputError").setHTML( "" );
	input.removeClass( "error" );
}

function inputValueMustBeGreaterThanZero( v )
{
	if ( !( v > 0 ) ) return "Value must be greater than zero";
	return null;
}

function inputValueMustBeAtLeastZero( v )
{
	if ( v < 0 ) return "Value must be greater than or equal to zero";
	return null;
}

function efficiencyValidator( v )
{
	if ( v < 0 || v > 1 ) return "Efficiency must be from zero to one";
	return null;
}


/**
	Convert 'value' in US Dollars to the currency 'currency' which must be defined in /conversion_rates.json
*/
function USDToCurrency( currency, value )
{
	return conversion_rates[ currency ] * value;
}

/**
	Convert 'value' in 'currency' to USD
*/
function CurrencyToUSD( currency, value )
{
	return value / conversion_rates[ currency ];
}

function toggleAssumptions()
{
	if ( AssumptionsShowing ) hideAssumptions();
	else showAssumptions();
}

function showAssumptions()
{
	var assumptions = $('assumptions');
	var content = $('content');
	var masthead = $('masthead');

	if ( assumptions )
	{
		AssumptionsShowing = true;

		assumptions.setStyle( "opacity", 0 );
		assumptions.setStyle( "display", "block" );
		
		var effects = assumptions.effects( { duration: 500, transition: Fx.Transitions.Quint.easeOut });
		effects.start(
			{
				'top': [20,30],
				'opacity': [0,1]
			});

		content.effects( 
			{ 
				duration: 1000, 
				transition: Fx.Transitions.linear 
			}).start(
			{
				'opacity':[1,0.2]
			});

		masthead.effects( 
			{ 
				duration: 1000, 
				transition: Fx.Transitions.linear 
			}).start(
			{
				'opacity':[1,0.2]
			});

		var IEVersion = window.self.navigator.appVersion;
		var IsIE6;
		if(IEVersion.indexOf("MSIE 6.0")>0)
			IsIE6 = true;
		else
			IsIE6 = false;

		if ( IsIE6 )
		{
			$$('input').each( function( input )
			{
				input.setStyle( "visibility", "hidden" );
			});

			$$('select').each( function( input )
			{
				input.setStyle( "visibility", "hidden" );
			});
		}

	}
	else
	{
		alert( "Can't find 'assumptions' block" );
	}

}

function hideAssumptions()
{
	var assumptions = $('assumptions');
	var content = $('content');
	var masthead = $('masthead');

	if ( assumptions )
	{
		AssumptionsShowing = false;
	
		var effects = assumptions.effects( 
			{ 
				duration: 500, 
				transition: Fx.Transitions.Quint.easeIn,
				onComplete: function()
				{
					assumptions.setStyle( "display", "none" );
				}
			});

		effects.start(
			{
				'top': [30,40],
				'opacity': [1,0]
			});

		content.effects( 
			{ 
				duration: 1000, 
				transition: Fx.Transitions.linear 
			}).start(
			{
				'opacity':1
			});

		masthead.effects( 
			{ 
				duration: 1000, 
				transition: Fx.Transitions.linear 
			}).start(
			{
				'opacity':1
			});

		var IEVersion = window.self.navigator.appVersion;
		var IsIE6;
		if(IEVersion.indexOf("MSIE 6.0")>0)
			IsIE6 = true;
		else
			IsIE6 = false;


		if ( IsIE6 )
		{
			$$('input').each( function( input )
			{
				input.setStyle( "visibility", "visible" );
			});

			$$('select').each( function( input )
			{
				input.setStyle( "visibility", "visible" );
			});
		}

	}
	else
	{
		alert( "Can't find 'assumptions' block" );
	}	
}


function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

///////////////////////////////////////////////////////////////////////
// Bootstrap ( when window's DOM is ready )
///////////////////////////////////////////////////////////////////////
	
window.addEvent( 'domready', function() {
	initializeCalculator();
});

