/*
* Javascript object for calculating shipping cost
* This object needs two linked scripts (bottleInZone.js and zoneChart.js)
*
* @author pclancy
* @date 04/26/06
*/

/**
 * Constructor for shipping cost.
 *
 * @param	{String}	n 		Instance name for a object.
 * @param	{String}	zipId	The id for the zip code input element.
 * @param	{String}	nbId	The id for the number of bottles input element.
 * @param	{String}	tsId	The id for the type of service select element.
 * @param	{String}	tId		The id for the total display field input element.
 * @param	{String}	stId	The id for the subtotal display field input element used to apply insurance.
 */
shipCost = function(n, zipId, nbId, tsId, tId, stId) {
	// set up object props
	this.instanceName = n;
	this.totalId = (tId == undefined) ? null : tId;
	this.subtotalId = (stId == undefined) ? null : stId;
	this.zipCodeId = (zipId == undefined) ? null : zipId;
	this.bottlesId = (nbId == undefined) ? null : nbId;
	this.serviceId = (tsId == undefined) ? null : tsId;
	//this object needs three linked scripts (bottleInZone.js, zoneChart.js, zoneExceptions.js)
	document.write('<script type="text/javascript" language="JavaScript1.2" src="/scripts/bottleInZone.js"></script>');
	document.write('<script type="text/javascript" language="JavaScript1.2" src="/scripts/zoneChart.js"></script>');
	document.write('<script type="text/javascript" language="JavaScript1.2" src="/scripts/zoneExceptions.js"></script>');
};
/**
* Calculate the shipping costs for x number of bottles, for zone x, with x type of service.
* Using the form elements passed into the constructor.
*
*/
shipCost.prototype.calShipping = function() {
	var zipElm = document.getElementById(this.zipCodeId);
	var bcElm = document.getElementById(this.bottlesId);
	var stElm = document.getElementById(this.serviceId);
	
	if (this.isValid(zipElm, bcElm, stElm)) {
		// first check for zip code exceptions - AK and HI
		var exceptionZoneModifier = "";
		var zoneList;
		zoneList = this.checkExceptionZipCodes(zipElm.value); // check excepts
	if (zoneList != null) {
		//alert("exception zone = " + zoneList[stElm.options[stElm.selectedIndex].value]);
		exceptionZoneModifier = "E";
	} else {
		// check our standard zip code lookup.
		var first3 = zipElm.value.toString().substring(0,3);
		zoneList = this.getZoneList(first3);
	}
	var zcode = zoneList[stElm.options[stElm.selectedIndex].value];
	if (zcode != null) { // some vales are null, also if not found null is returned
		var zcodestr = zcode.toString();
		var zn = zcodestr.substring(zcodestr.length-1, zcodestr.length);
		var cost = this.costOfPackedBottles(bcElm.value, (exceptionZoneModifier + zn), stElm.options[stElm.selectedIndex].value);
		// add any flat fees per transaction
		cost = cost + this.addFlatFeePerTransaction();
		// if we can get a subtotal then try to apply insurance cost
		if (this.subtotalId && document.getElementById(this.subtotalId)) {
			cost = cost + this.calInsurance(document.getElementById(this.subtotalId).value); // parseInt
		}
		// if we have a field id display the total in the field
		if (this.totalId && document.getElementById(this.totalId)) {
			document.getElementById(this.totalId).value = '$ '+cost;
			return;
		}
	return cost;
	} else {
		alert ("The selected type of service is not available for your location.");
	}
	}
};
/**
* Calculate the total based on splitting the number of bottles accross the number of boxes.
*
* @param	{Integer}	cost	The destination zip code
* @return	{Integer}			The total cost for the boxes  
*/
shipCost.prototype.costOfPackedBottles = function(bc, zn, st) {
var Total = 0;
var boxes = {"twelve":0, "six":0, "three":0, "two":0, "one":0};
// Adjust our bottle count based on the gaps
var bottleCount = this.getBottlesBasedOnGaps(bc);
var rbc = bottleCount;
// put together the boxes into largest to smallest groups
if (bottleCount >= 12) {
 boxes.twelve = Math.floor(bottleCount/12);
 rbc = bottleCount - boxes.twelve * 12;
} 
if (rbc >= 6) {
	boxes.six = Math.floor(rbc/6);
		rbc = rbc - boxes.six * 6;
}
if (rbc < 6 && rbc >= 3) {
	boxes.three = Math.floor(rbc/3);
		rbc = rbc - boxes.three * 3;
}
if (rbc < 3 && rbc >= 2) {
	boxes.two = Math.floor(rbc/2);
		rbc = rbc - boxes.two * 2;
}
if (rbc >= 1) {
	boxes.one = rbc;
}
// alert test to show the bottle groupings per box	
//alert("total bottles = "+ bc +"\n 12=" + boxes.twelve + "\n6=" + boxes.six + "\n3=" + boxes.three + "\n2=" + boxes.two + "\n1=" + boxes.one);
for (box in boxes) {
if (box == "twelve") {
	for (var x=0; x<boxes[box]; x++) {
		Total = Total + bottlesInZone["b12"]["zone"+zn][st];
	}
}
if (box == "six") {
	for (var x=0; x<boxes[box]; x++) {
		Total = Total + bottlesInZone["b6"]["zone"+zn][st];
	}
}
if (box == "three") {
	for (var x=0; x<boxes[box]; x++) {
		Total = Total + bottlesInZone["b3"]["zone"+zn][st];
	}
}
if (box == "two") {
	for (var x=0; x<boxes[box]; x++) {
		Total = Total + bottlesInZone["b2"]["zone"+zn][st];
	}
}
if (box == "one") {
	for (var x=0; x<boxes[box]; x++) {
		Total = Total + bottlesInZone["b1"]["zone"+zn][st];
	}
}
}
return Total;
};
/**
* Calculate the Insurance cost for a total $ ammount.
*
* @param	{Integer}	cost	The destination zip code
* @return	{Integer}			The Insurance cost
*/
shipCost.prototype.calInsurance = function(cost) {
	if (cost == undefined || !this.isNumber(cost) || cost <= 100) {
		return 0;
	} else if (cost > 100 && cost <= 400) {
		return 1;
	} else if (cost > 400 && cost <= 500) {
		return 2;
	} else {
		return Math.ceil((cost/100));
	}
	
};
/**
* Adjust the bottle count based on these gaps.
* (4=3) (5,6,7,8,9 = 6) (10,11 = 12)
*/
shipCost.prototype.getBottlesBasedOnGaps = function(bottles) {
if (bottles == undefined || !this.isNumber(bottles)) {
return;
} else if (bottles == 4) {
return 3;
} else if (bottles >= 5 && bottles <= 9) {
return 6;
} else if (bottles >= 10 && bottles <= 11) {
return 12;
} else {
return bottles;
}
};
/** Add a $3 flat fee per transaction
*
*/
shipCost.prototype.addFlatFeePerTransaction = function() {
return 3;
};
/**
* Determine the shipping zone based on the first three number in their destination zip code.
* Return a service zone object. {"s":004, "e":005, "ground":8, "3day":308, "2day":208, "nextDay":108}
*
* @param	{String}	zip		The destination zip code
* @return	{Object}		
*/
shipCost.prototype.getZoneList = function(zip) {
	var count=zones.length;
	for (var i=0; i<count; i++) {
		if (zip >= zones[i].s && zip <= zones[i].e) {
			return zones[i];
		}
	}
	return null;
};
/**
* Determine the shipping zone based on the zip code. This is un against our list of exception zip codes. If
* not found in any of the lists. We run the standard zone lookup.
* Return a service zone object. {"z":[array of zips], "ground":8, "3day":308, "2day":208, "nextDay":108}
*
* @param	{String}	zip		The destination zip code
* @return	{Object}		
*/
shipCost.prototype.checkExceptionZipCodes = function(zip) {
	var count=excptZones.length;
	for (var i=0; i<count; i++) {
		for (var j=0; j<excptZones[i].z.length; j++) {
			if (excptZones[i].z[j] == zip) {
				return excptZones[i];
			}
		}
	}
	return null;
};
/**
* Check to see that we have all required valid parameters.
*
* @param	{String}	zip		The destination zip code
* @param	{Integer}	b		The number of bottles being shipped
* @param	{String}	s		The type of service (ground, 3day air, 2day air, next day)
*/
shipCost.prototype.isValid = function(zip,b,s) {
	if (zip.value == "" || !this.isNumber(zip.value) || zip.value.length < 5) {
		alert("Please enter a valid 5 digit zip code.");
		return false;
	}
	// if (b.options[b.selectedIndex].value == "" || !this.isNumber(b.options[b.selectedIndex].value)) { // select version
	if (b.value == "" || !this.isNumber(b.value)) {
		alert("Please enter the number of bottles your shipping.");
		return false;
	}
	if (s.options[s.selectedIndex].value == "" || !this.isEmpty(s.options[s.selectedIndex].value)) {
		alert("Please select the type of shipping service.");
		return false;
	}
	return true;
};
/**
* Validate the value is a positive or negative number.
*
* @param	{Number}	val		The value to be checked.
* @return	{Boolean}
*/
shipCost.prototype.isNumber = function(val) {
	var re = /^[-]?\d*\.?\d*$/;
	var str = val.toString();
	if (!str.match(re)) {
		return false;
	}
	return true;
};
/**
* Validate the value is a positive or negative number.
*
* @param	{Number}	val		The value to be checked.
* @return	{Boolean}
*/
shipCost.prototype.isEmpty = function(val) {
	var re = /.+/;
	var str = val.toString();
	if (!str.match(re)) {
		return false;
	}
	return true;
};






