/**
 * Docking Calculation plugin
 * Written by Phil Munro / phil@inbusiness.no
 **/

(function($){
	
	$.fn.dockingCalculator = function(options,customLanguages){

		/* VARIABLES, SETTINGS AND CONSTANTS [START] */
		
			/* define the plugin defaults */
			var defaults = {
					containerID: 'portCalculator'
						
					/* price constants */
					,priceConstants: {
							callCharge_min: 215
							,dockingCharge_min: 400
							,ispsRate: 30
							,valueDecimalPlaces: 2
						}
	
					/* call rates */
					,callRates: [
						{limit: 600, price: 0.73},
						{limit: 4400, price: 0.47},
						{limit: 45000, price: 0.35},
						{limit: 1000000, price: 0.27}
					]
					
					/* docking rate */
					,dockingRates: [
						{limit: 300, price: 1.35},
						{limit: 300, price: 1.05},
						{limit: 2400, price: 0.55},
						{limit: 7000, price: 0.55},
						{limit: 20000, price: 0.45},
						{limit: 1000000, price: 0.35}
					]
					,language: { 
						error_tonnage_empty: '[error_tonnage_empty]'
						,error_tonnage_invalid: '[error_tonnage_invalid]'
						,header: '[header]'
						,label_tonnage: '[label_tonnage]'
						,label_isps: '[label_isps]'
						,isps_yes: '[isps_yes]'
						,isps_no: '[isps_no]'
						,button_text: '[button_text]'
						,result_intro: '[results_intro]'
						,result_charge_quay: '[result_charge_quay]'
						,result_charge_isps: '[result_charge_isps]'
						,result_charge_call: '[result_charge_call]'
						,result_charge_total: '[result_charge_total]'
					}
					
					
			};
		
		
			/* define the various HTML elements needed on the page */
			var html = {		
					/* "calculate" button */
					form_button:	function(){
										var html_snippet = '';
										html_snippet = html_snippet + '<div class="clearHidden">&nbsp;</div>';
										html_snippet = html_snippet + '<input type="button" id="button_calculate" value="'+ getPhrase('button_text') +'" />';
										html_snippet = html_snippet + '<br /><br />';
										return html_snippet;
									},
					/* ISPS radio button */
					form_isps:		function(){
										var html_snippet = '';
										html_snippet = html_snippet + '<span class="fake_inlineLabel">'+ getPhrase('label_isps') +':</span>';
										
										/* "yes" radio */
										html_snippet = html_snippet + '<input type="radio" name="ISPS" id="ISPS_yes" value="yes" />';
										html_snippet = html_snippet + '<label for="ISPS_yes" class="label">'+ getPhrase('isps_yes') +'</label>';
										
										html_snippet = html_snippet + '&nbsp;&nbsp;&nbsp;';
										
										/* "no" radio */
										html_snippet = html_snippet + '<input type="radio" name="ISPS" id="ISPS_no" value="no" checked="true" />';
										html_snippet = html_snippet + '<label for="ISPS_no" class="label">'+ getPhrase('isps_no') +'</label>';
										
										html_snippet = html_snippet + '<br />';
										
										return html_snippet;
									},
									
					/* tonnage field */
					form_tonnage:	function(){
										var html_snippet = '';
										html_snippet = html_snippet + '<label for="tonnage" class="inlineLabel">'+ getPhrase('label_tonnage') +':</label>';
										html_snippet = html_snippet + '<input type="text" name="tonnage" id="tonnage" class="textField tonnage validate [required]" />';
										html_snippet = html_snippet + '<span id="tonnage_error"></span>';
										html_snippet = html_snippet + '<br /><br />';
										return html_snippet;
									},
									
					/* header */
					header:			function(){
										var html_snippet = '';
										html_snippet = html_snippet + '<h2>'+ getPhrase('header') +'</h2>';
										return html_snippet;
									},
									
					/* results table */
					results_table:	function(){
										var html_snippet = '';
										html_snippet = html_snippet + '<div id="CalculatedPrices">';
										html_snippet = html_snippet + getPhrase('result_intro');
										html_snippet = html_snippet + '<table id="prices">';
										html_snippet = html_snippet + '<tr><th scope="row">'+ getPhrase('result_charge_quay') +':</th><td id="charge_daily"></td></tr>';
										html_snippet = html_snippet + '<tr><th scope="row">'+ getPhrase('result_charge_isps') +':</th><td id="charge_isps"></td></tr>';
										html_snippet = html_snippet + '<tr><th scope="row">'+ getPhrase('result_charge_call') +':</th><td id="charge_call"></td></tr>';
										html_snippet = html_snippet + '<tr><th scope="row">'+ getPhrase('result_charge_total') +':</th><td id="charge_total"></td></tr>';
										html_snippet = html_snippet + '</table></div>';
										return html_snippet;
									}
				};

			
			/* build the settings (use the defaults, together with the options provided) */
			var settings = $.extend(defaults, options);
		
		/* VARIABLES, SETTINGS AND CONSTANTS [END] */
			
		
			
		/* METHODS [START] */
			/* method to return a phrase from the language pack */
			var getPhrase = function(phrase){
					var lcl = {};
					if(typeof(settings.language[phrase]) == 'undefined'){
						lcl.translation = '['+ phrase +']';
					}
					else{
						lcl.translation = settings.language[phrase];
					}
					return lcl.translation;
				};
			
	
			/* Calculate Call Charge [START] */
				var calculateCharge_call = function(tonnage){
					var lcl = {};
					
					/* prepare the variables needed */
					lcl.callCharge = 0;
					lcl.callRates_len = settings.callRates.length;
					lcl.tonnage_remainder = tonnage;
					
					/* loop through the call rates and apply the necessary charges */
					for(lcl.callRates_i = 0; lcl.callRates_i < lcl.callRates_len; lcl.callRates_i++){
						/* if the remaining tonnage is empty, break out the loop - otherwise continue */
						if(lcl.tonnage_remainder == 0){
							break;
						}
						
						/* get the current rate */
						lcl.currentRate = settings.callRates[lcl.callRates_i];
		
						/* clear the rateable tonnage for each rate looped */
						lcl.rateableTonnage = 0;
						
						/* calculate how much */
						if(lcl.tonnage_remainder > lcl.currentRate.limit){
							lcl.rateableTonnage = lcl.currentRate.limit;
						}
						else {
							lcl.rateableTonnage = lcl.tonnage_remainder;
						}
						
						/* update the remaining tonnage that needs to be calculated at the next rate */
						lcl.tonnage_remainder = lcl.tonnage_remainder - lcl.rateableTonnage;
				
						/* calculate the charge on this particular portion of the tonnage */
						lcl.rateCharge = lcl.rateableTonnage * lcl.currentRate.price;
										
						/* add the charges incurred at this rate, onto the overall running total */
						lcl.callCharge = lcl.callCharge + lcl.rateCharge;
					}
					
					/* enforce the minimum call charge if necessary */
					if(lcl.callCharge < settings.priceConstants.callCharge_min){
						lcl.callCharge = settings.priceConstants.callCharge_min;
					}
					
					/* return the call charge */
					return lcl.callCharge;
				};
			/* Calculate Call Charge [END] */
			
			
			/* Calculate Dock Charge [START] */
				var calculateCharge_docking = function(tonnage){
					var lcl = {};
					
					/* prepare the variables needed */
					lcl.dockingCharge = 0;
					lcl.dockingRates_len = settings.dockingRates.length;
					lcl.tonnage_remainder = tonnage;
					
					/* loop through the call rates and apply the necessary charges */
					for(lcl.dockingRates_i = 0; lcl.dockingRates_i < lcl.dockingRates_len; lcl.dockingRates_i++){
						/* if the remaining tonnage is empty, break out the loop - otherwise continue */
						if(lcl.tonnage_remainder == 0){
							break;
						}
						
						/* get the current rate */
						lcl.currentRate = settings.dockingRates[lcl.dockingRates_i];
		
						/* clear the rateable tonnage for each rate looped */
						lcl.rateableTonnage = 0;
						
						/* calculate how much */
						if(lcl.tonnage_remainder > lcl.currentRate.limit){
							lcl.rateableTonnage = lcl.currentRate.limit;
						}
						else {
							lcl.rateableTonnage = lcl.tonnage_remainder;
						}
						
						/* update the remaining tonnage that needs to be calculated at the next rate */
						lcl.tonnage_remainder = lcl.tonnage_remainder - lcl.rateableTonnage;
				
						/* calculate the charge on this particular portion of the tonnage */
						lcl.rateCharge = lcl.rateableTonnage * lcl.currentRate.price;
										
						/* add the charges incurred at this rate, onto the overall running total */
						lcl.dockingCharge = lcl.dockingCharge + lcl.rateCharge;
					}
					
					/* enforce the minimum call charge if necessary */
					if(lcl.dockingCharge < settings.priceConstants.dockingCharge_min){
						lcl.dockingCharge = settings.priceConstants.dockingCharge_min;
					}
					
					/* return the call charge */
					return lcl.dockingCharge;
				};
			/* Calculate Dock Charge [END] */
				
				
			/* Calculate ISPS Charge [START] */
				var calculateCharge_isps = function(dockCharge){
					var lcl = {};
					
					lcl.ispsCharge = 0;
					
					/* if ISPS */
					if($('#ISPS_yes').attr('checked') == true){
						lcl.ispsCharge = (dockCharge * settings.priceConstants.ispsRate) / 100;
					}
					
					return lcl.ispsCharge;
				};
			/* Calculate ISPS Charge [END] */
				
				
			
			/* start calculating the charge */
			var calculateCharges = function(){
				
				var lcl = {};
				
				/* get the tonnage from the form */
				lcl.tonnage = $('#tonnage').val();
				
				/* validate the tonnage entered */
				if(validateTonnage(lcl.tonnage) == false){
					$('#CalculatedPrices').slideUp(500);
					return false;
				}
				
				/* get the call charge */
				lcl.callCharge = calculateCharge_call(lcl.tonnage);
				
				/* get the docking charge */
				lcl.dockingCharge = calculateCharge_docking(lcl.tonnage);
				
				/* get the ISPS charge */
				lcl.ispsCharge = calculateCharge_isps(lcl.dockingCharge);
				
				/* calculate the totals */
				lcl.totalCharge = lcl.callCharge + lcl.dockingCharge + lcl.ispsCharge;
				
				/* write the charges to the view */
				$('#charge_call').text('kr. '+ lcl.callCharge.toFixed(settings.priceConstants.valueDecimalPlaces));
				$('#charge_daily').text('kr. '+ lcl.dockingCharge.toFixed(settings.priceConstants.valueDecimalPlaces));
				$('#charge_isps').text('kr. '+ lcl.ispsCharge.toFixed(settings.priceConstants.valueDecimalPlaces));
				$('#charge_total').text('kr. '+ lcl.totalCharge.toFixed(settings.priceConstants.valueDecimalPlaces));
				
				$('#CalculatedPrices').slideDown(500);
			};
			
			
			/* prepare the plugin */
			var init = function(){
				
				var lcl = {};
				
				lcl.pluginContainer = $('#'+ settings.containerID);
				
				/* add the header */
				lcl.pluginContainer.append(html.header());
				
				/* add the form elements */
				lcl.pluginContainer.append(html.form_tonnage());
				lcl.pluginContainer.append(html.form_isps());
				lcl.pluginContainer.append(html.form_button());
				
				/* add the results table */
				lcl.pluginContainer.append(html.results_table());
				
				
				/* listen for the calculate button getting clicked */
				$('#button_calculate').click(function(){
					calculateCharges();
				});
			};
			
			
			/* validate the tonnage entered */
			var validateTonnage = function(tonnage){
				var lcl = {};
				lcl.success = true;
				lcl.error = '';
				
				/* check for errors */
				if(isNaN(tonnage) || (tonnage < 0)){
					lcl.success = false;
					lcl.error = getPhrase('error_tonnage_invalid');
				}
				else if((tonnage == '') || (tonnage == 0)){
					lcl.success = false;
					lcl.error = getPhrase('error_tonnage_empty');
				}
				
				/* hide or show the error message as necessary */
				if(lcl.success == false){
					$('#tonnage_error').text(lcl.error);
					$('#tonnage_error').show();
				}
				else {
					$('#tonnage_error').hide();
				}
				
				return lcl.success;
			}
		
		/* METHODS [END] */
			
	
		/* initialising the plugin */
		init();		
		
	};	
})
(jQuery);
