/*
* StandardEngine.js - Standard Quote Engine
* Written by AMaitland
* Version 1.1
*/

// Enhancement of prototype evalJSON to handle Date objects output from .Net Javascript Serializer
String.prototype.evalJSONWithDates = function() {
	var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
	return jsonWithDates.evalJSON();
}

// Override of prototype toJSON so Date objects match syntax of .Net Javascript Serializer
Date.prototype.toJSON = function() {
	return '"\\\/Date(' + this.getTime() + ')\\\/"';
};

//Standard quote AJAX call return
function standardCalculate(response)
{
	var xmldoc = response.responseXML.documentElement;
	var items = xmldoc.getElementsByTagName("PREMIUM");

	if (items == null || items.length == 0)
	{
		
		_errorDisplayControlStandard.AppendAndDisplayWarning("An error occured whilst obtaining your quote, please validate your quote details are correct.");
	}
	else
	{
		for (var i = 0; i < items.length; i++)
		{
			var attr = items[i].attributes;
			var id = parseInt(attr[0].nodeValue, 10);
			var amount = attr[1].nodeValue;
			var destination = attr[2].nodeValue;
			var planControl = findPlanControlById(_planControlArray, id);
			planControl.setDestination(destination);
			planControl.setPremium(amount);
		}
	}
	$('imgArrowProcessing').hide();
	$('imgArrowStatic').show();
};

function findPlanControlById(controlArray, id)
{
	for (var i = 0; i < controlArray.length; i++)
	{
		if (controlArray[i].PlanSet.PlanSetId == id)
		{
			return controlArray[i];
		}
	}
	return null;
}

function standardTimeout()
{
	_errorDisplayControlStandard.AppendAndDisplay("Your quote request timed out, please try again.");
	$('imgArrowProcessing').hide();
	$('imgArrowStatic').show();
}

function standardQuote(quoteControl, quoteService, planSets)
{
	var quote = quoteControl.getQuote();

	quoteService.Submit(quote.Adults, quote.Dependants, quote.Destination, quote.StartDate, quote.EndDate, planSets, quote.PromotionCode, quote.AffiliateCode);
}

function escapeHTML(str)
{
	var div = document.createElement('div');
	var text = document.createTextNode(str);
	div.appendChild(text);
	return div.innerHTML;
};

function cbStandardQuoteChange(o)
{
	$('imgArrowStatic').hide();
	$('imgArrowProcessing').show();

	var planSets = _website == null ? _planSets : _website.PlanSets;

	standardQuote(_quoteControl, _standardQuoteService, planSets);
	var quote = _quoteControl.getQuote();
	for (var i = 0; i < _planControlArray.length; i++)
	{
		_planControlArray[i].setDestination(quote.Destination);
		// put the selected destination into each element of the plan control array
		_planControlArray[i].NewDestination = quote.Destination;
	}

	_errorDisplayControlStandard.Hide();
	var isBasicValid = _basicValidator.Validate();
	if (isBasicValid)
	{
		var errors = new Array();
		var noOfErrors = 0;
		for (var i = 0; i < _planControlArray.length; i++)
		{
			var validator = _planControlArray[i].getValidator(_quoteControl, _today, _todayPlusOneYear, _todayPlusTwoYear);
			var isValid = validator.Validate();
			if (!isValid)
			{
				noOfErrors = noOfErrors + 1;
				errors.push(_planControlArray[i].SelectedPlan.Description + ": " + validator.ValidateMessage);
			}
		}
		if (noOfErrors < _planControlArray.length)
		{
			if (noOfErrors != 0)
			{
				_errorDisplayControlStandard.AppendAndDisplayWarning(errors);
			}
		}
		else
		{
			_errorDisplayControlStandard.AppendAndDisplay(errors);
		}
	}
	else
	{
		_errorDisplayControlStandard.AppendAndDisplay(_basicValidator.ValidateMessage);
	}
}

function onChange_EndMonthYear(evt)
{
	var endDate = Event.element(evt).value;
	_quoteControl.EndDate.updateDays(endDate);
	evt.stop();
}

function onChange_StartMonthYear(evt)
{
	var startDate = Event.element(evt).value;
	_quoteControl.StartDate.updateDays(startDate);
	_quoteControl.EndDate.resetEndDates(_arrEndDates);
	evt.stop();
}

function IsDomestic(destination)
{
	if (destination.toUpperCase() == 'AUSTRALIA')
	{
		return true;
	}
	return false;
}

/*
* SABLib.js - Select a Benefit Quoting Engine
* Written by AMaitland
* Version 1.1
*/

Mondial =
{
	//Standard Mode (Multi Quote)
	QUOTE_MODE_STANDARD: 0,
	//Select a Benefit Mode
	QUOTE_MODE_SAB: 1,
	SAB_COOKIE_NAME: "worldcareSABCookie",
	IEBrowserVersion: parseFloat(navigator.appVersion.split('MSIE')[1]),
	//TODO: tidy up some of this
	Browser:
	{
		IEBrowserVersion: parseInt(navigator.appVersion.split('MSIE')[1], 10),
		IE6: parseInt(navigator.appVersion.split('MSIE')[1], 10) == 6
	},
	ApplyPNGFix: ((this.IEBrowserVersion >= 5.5) && (this.IEBrowserVersion < 7) && (document.body.filters)),
	//Create Mondial.Ajax namespace
	Ajax: {},
	MapTimeUnit: function(unit)
	{
		var unitInt = parseInt(unit, 10);
		if (unitInt == 0)
		{
			return "Day";
		}
		if (unitInt == 1)
		{
			return "Month";
		}
		//Default Return of "Year"
		return "Year";
	}
};

Mondial.BasicValidator = Class.create(
{
	ValidateMessage: "OK",
	StartDate: null,
	EndDate: null,
	Today: null,
	PurchaseCutOff: null,
	TodayPlusTwoYears: null,

	initialize: function(dmyStartDate, dmyEndDate, sdToday, sdPurchaseCutOff, todayPlusTwoYears)
	{
		this.StartDate = dmyStartDate;
		this.EndDate = dmyEndDate;
		this.Today = sdToday;
		this.PurchaseCutOff = sdPurchaseCutOff;
		this.TodayPlusTwoYears = todayPlusTwoYears;
	},
	IsStartDateValid: function()
	{
		//Validate start date
		var dteStart = this.StartDate.GetSimpleDate();
		var dteEnd = this.EndDate.GetSimpleDate();
		dteStart.MinRange = this.Today.ToString();
		dteStart.MaxRange = this.PurchaseCutOff.ToString();

		if (!dteStart.IsGreater(this.Today.ToString()))
		{
			this.ValidateMessage = "Start date is invalid. Earliest possible start date is " + this.Today.ToString();
			return false;
		}
		if (!dteStart.IsInRange())
		{
			this.ValidateMessage = "Start date is invalid. Policy start dates must be between " + this.Today.ToString() + " and " + dteStart.MaxRange;
			return false;
		}

		return true;
	},
	IsEndDateValid: function()
	{
		//Validate end date
		var dteStart = this.StartDate.GetSimpleDate();
		var dteEnd = this.EndDate.GetSimpleDate();
		dteEnd.MinRange = this.Today.ToString();
		dteEnd.MaxRange = this.TodayPlusTwoYears.ToString();

		if (!dteEnd.IsInRange())
		{
			this.ValidateMessage = "Policy End Date must be between " + this.Today.ToString() + " and " + dteEnd.MaxRange;
			return false;
		}
		if (!dteEnd.IsGreater(dteStart.ToString()))
		{
			this.ValidateMessage = "End Date must come after Start Date";
			return false;
		}

		return true;
	},
	Validate: function()
	{
		this.ValidateMessage = "OK";

		return this.IsStartDateValid() && this.IsEndDateValid();
	}
});

Mondial.QuoteValidator = Class.create(
{
	StartDate: null,
	EndDate: null,
	ValidateMessage: "OK",
	Today: null,
	PurchaseCutOff: null,
	MaxLength: null,
	MaxLengthUnit: null,
	TodayPlusTwoYears: null,

	initialize: function(dmyStartDate, dmyEndDate, sdToday, sdPurchaseCutOff, todayPlusTwoYears, intMaxLength, strMaxLengthUnit)
	{
		this.StartDate = dmyStartDate;
		this.EndDate = dmyEndDate;
		this.Today = sdToday;
		this.PurchaseCutOff = sdPurchaseCutOff;
		this.MaxLength = parseInt(intMaxLength, 10);
		this.MaxLengthUnit = strMaxLengthUnit;
		this.TodayPlusTwoYears = todayPlusTwoYears;
	},
	IsStartDateValid: function()
	{
		//Validate start date
		var dteStart = this.StartDate.GetSimpleDate();
		var dteEnd = this.EndDate.GetSimpleDate();
		dteStart.MinRange = this.Today.ToString();
		dteStart.MaxRange = this.PurchaseCutOff.ToString();

		if (!dteStart.IsGreater(this.Today.ToString()))
		{
			this.ValidateMessage = "Start date is invalid. Earliest possible start date is " + this.Today.ToString();
			return false;
		}
		if (!dteStart.IsInRange())
		{
			this.ValidateMessage = "Start date is invalid. Policy start dates must be between " + this.Today.ToString() + " and " + dteStart.MaxRange;
			return false;
		}

		return true;
	},
	IsEndDateValid: function()
	{
		//Validate end date
		var dteStart = this.StartDate.GetSimpleDate();
		var dteEnd = this.EndDate.GetSimpleDate();
		dteEnd.MinRange = this.Today.ToString();
		dteEnd.MaxRange = this.TodayPlusTwoYears.ToString();

		if (!dteEnd.IsInRange())
		{
			this.ValidateMessage = "Policy End Date must be between " + this.Today.ToString() + " and " + dteEnd.MaxRange;
			return false;
		}
		if (!dteEnd.IsGreater(dteStart.ToString()))
		{
			this.ValidateMessage = "End Date must come after Start Date";
			return false;
		}

		if (!this.ValidateMaxLength(this.MaxLength, this.MaxLengthUnit))
		{
		  this.ValidateMessage = "Policy Length cannot exceed " + this.MaxLength + " " + this.MaxLengthUnit + (this.MaxLengthUnit.toLowerCase() == "year" ? "" : "(s)");
			return false;
		}

		return true;
	},
	ValidateMaxLength: function()
	{
		var dteStartDate = this.StartDate.GetSimpleDate().GetDate();
		var dteEndDate = this.EndDate.GetSimpleDate().GetDate();

		var syear = 0;
		var unit = this.MaxLengthUnit.toLowerCase();

		if (/year/.test(unit))
		{
			// add number of years and then turn into a date
			syear = parseInt(dteStartDate.getFullYear(), 10) + parseInt(this.MaxLength, 10);
			dteStartDate.setYear(syear);
		}
		else if (/month/.test(unit))
		{
			smonth = parseInt(dteStartDate.Month, 10) + parseInt(this.MaxLength, 10);
			if (smonth > 12)
			{
				smonth = parseInt(smonth, 10) - 12;
				syear = parseInt(syear, 10) + 1;
			}

			dteStartDate.setMonth(smonth - 1);
		}
		else if (/day/.test(unit))
		{
			var length = parseInt(this.MaxLength, 10) - 1;
			dteStartDate.setDate(dteStartDate.getDate() + length);
		}

		if (dteEndDate.getTime() >= dteStartDate.getTime())
		{
			return false;
		}
		else
		{
			return true;
		}
	},
	Validate: function()
	{
		this.ValidateMessage = "OK";

		return this.IsStartDateValid() && this.IsEndDateValid();
	}
});

Mondial.DMYControl = Class.create(
{
	/// <summary>
	/// DMYControl - Represents a Two Part Date Control (Day and Month+Year)
	/// Both the Day control and Month+Year controls MUST be dropdown's
	/// </summary>
	/// <param name="ddDay">The day drop down list</param>
	/// <param name="ddMonthYear">The Month+Year drop down list</param>
	/// <param name="strInitialDate">The initial date in string format (dd/MM/yyyy)</param>
	initialize: function(ddDay, ddMonthYear, initialDate)
	{
		this.DDDay = $(ddDay);
		this.DDMonthYear = $(ddMonthYear);
		this.InitialDate = typeof (initialDate) == 'object' ? new Mondial.SimpleDate().ParseDate(initialDate) : new Mondial.SimpleDate().ParseString(initialDate);
		this.updateMonthOnLoad(this.InitialDate.ToMonthYearStr(), this.InitialDate.Day);
	},
	GetSimpleDate: function()
	{
		return new Mondial.SimpleDate().ParseTwoPartDate(this.DDDay.value, this.DDMonthYear.value);
	},
	updateDate: function(strDate) {
		this.UpdateSimpleDate(new Mondial.SimpleDate().ParseString(strDate));
	},
	UpdateSimpleDate: function(dte) {
		var strMonthYear = dte.ToMonthYearStr();

		for (var i = 0; i < this.DDDay.options.length; i++) {
			if (parseInt(this.DDDay.options[i].value, 10) == dte.Day) {
				this.DDDay.options[i].selected = true;
			}
		}

		for (i = 0; i < this.DDMonthYear.options.length; i++) {
			if (this.DDMonthYear.options[i].value == strMonthYear) {
				this.DDMonthYear.options[i].selected = true;
			}
		}
	},
	updateMonthOnLoad: function(strMonthYear, strDay)
	{
		var dte = new Mondial.SimpleDate().ParseString("01/" + strMonthYear);

		var intDaysInMonth;

		try
		{
			intDaysInMonth = dte.DaysInMonth();
		}
		catch (err)
		{
			//Ignore this error
		}

		//Check to see if days in month is ok.
		if (intDaysInMonth >= 28)
		{
			var dteCurrent = new Mondial.SimpleDate().Now();
			var dte = dteCurrent.ToMonthYearStr();
			var avaliableDays = intDaysInMonth - dteCurrent.Day;

			//If the month is the current, the remove all past dates and adjust
			// number of days in month
			if (strMonthYear == dte)
			{
				if (intDaysInMonth < this.DDMonthYear.options.length)
				{
					while (this.DDMonthYear.options.length > intDaysInMonth)
					{
						this.removeSelectElement(ddControl, ddControl.length - 1);
					}
				}
			}
		}

		this.UpdateSimpleDate(this.InitialDate);
	},
	//Wrapper function around the remove, incase we need to implement some backwards compatable functions
	removeSelectElement: function(dd, intIndex)
	{
		dd.removeChild(dd.options[intIndex]);
	},
	updateDays: function(strMonthYear)
	{
		var ddControl = $(this.DDDay);
		var dte = new Mondial.SimpleDate().ParseString("01/" + strMonthYear);

		var intDaysInMonth;

		try
		{
			intDaysInMonth = dte.DaysInMonth();
		}
		catch (err)
		{
			//Ignore this error
		}

		//Check to see if days in month is ok.
		if (intDaysInMonth >= 28)
		{
			var dteCurrent = new Mondial.SimpleDate().Now();
			var avaliableDays = intDaysInMonth - dteCurrent.Day + 1;

			//If the month is the current, the remove all past dates and adjust
			// number of days in month
			if (strMonthYear == dteCurrent.ToMonthYearStr())
			{
				if (ddControl.length < intDaysInMonth)
				{
					while (parseInt((ddControl.options[ddControl.length - 1].value), 10) != intDaysInMonth)
					{
						var intVal = parseInt((ddControl.options[ddControl.length - 1].value), 10) + 1;
						this.createAppendOption(ddControl, intVal);
					}
				}

				if (intDaysInMonth < ddControl.length)
				{
					while (ddControl.length > intDaysInMonth)
					{
						this.removeSelectElement(ddControl, ddControl.length - 1);
					}
				}

				if (ddControl.length > avaliableDays)
				{
					while (ddControl.length > avaliableDays)
					{
						this.removeSelectElement(ddControl, 0);
					}
				}
			}
			else
			{
				while (parseInt((ddControl.options[0].value), 10) != 1)
				{
					var op = document.createElement("option");
					var intVal = parseInt((ddControl.options[0].value), 10) - 1;
					op.innerHTML = intVal;
					op.value = intVal;
					ddControl.insertBefore(op, ddControl.options[0]);
				}

				if (intDaysInMonth < ddControl.length)
				{
					while (ddControl.length > intDaysInMonth)
					{
						this.removeSelectElement(ddControl, ddControl.length - 1);
					}
				}
				else
				{
					while (ddControl.length < intDaysInMonth)
					{
						var intVal = parseInt((ddControl.options[ddControl.length - 1].value), 10) + 1;
						this.createAppendOption(ddControl, intVal);
					}
				}
			}
		}
	},
	createAppendOption: function(ddParent, val)
	{
		var op = document.createElement("option");
		op.innerHTML = val;
		op.value = val;
		ddParent.appendChild(op);
	},
	updateEndDates: function(arrDates, intIndex)
	{
		this.resetEndDates(arrDates);

		for (var i = 0; i < intIndex; i++)
		{
			this.DDMonthYear.removeChild(this.DDMonthYear.options[0]);
		}

		var intTotal = 13;
		if (this.DDMonthYear.options.length == 12)
		{
			intTotal = 12;
		}

		while (this.DDMonthYear.options.length > intTotal)
		{
			this.DDMonthYear.removeChild(this.DDMonthYear.options[this.DDMonthYear.options.length - 1]);
		}
	},
	resetEndDates: function(arrDates)
	{
		if (this.DDMonthYear.options.length < arrDates.length)
		{
			var matchFound = false;

			for (var i = 0; i < arrDates.length; i++)
			{
				if (arrDates[i] != this.DDMonthYear.options[0] && !matchFound)
				{
					this.DDMonthYear.insertBefore(arrDates[i], this.DDMonthYear.options[i]);
				}
				else if (arrDates[i] != this.DDMonthYear.options[0])
				{
					this.DDMonthYear.appendChild(arrDates[i]);
				}
			}

			var intCount = arrDates.length - this.DDMonthYear.options.length;
			for (var i = intCount; i >= 0; i--)
			{
				this.DDMonthYear.insertBefore(arrDates[i], this.DDMonthYear.options[0]);
			}
		}
	}
});

Mondial.SimpleDate = Class.create(
{
	MaxRange: 0,
	MinRange: 0,
	initialize: function(intDay, intMonth, intYear)
	{
		this.Day = intDay;
		this.Month = intMonth;
		this.Year = intYear;
	},
	Now: function()
	{
		var dteCurrent = new Date();
		dteCurrent.setDate(dteCurrent.getDate());

		return this.ParseDate(dteCurrent);
	},
	ToMonthYearStr: function()
	{
		return this.padDate(this.Month) + "/" + this.Year;
	},
	GetDate: function()
	{
		//JS Month starts from 0-11
		return new Date(this.Year, parseInt(this.Month - 1, 10), this.Day);
	},
	padDate: function(intInput)
	{
		if (intInput < 10)
		{
			intInput = "0" + intInput;
		}
		return intInput;
	},
	ParseTwoPartDate: function(strDay, strMonthYear)
	{
		var intIndex = strMonthYear.indexOf("/");
		this.Day = parseInt(strDay, 10);
		this.Month = parseInt(strMonthYear.substring(0, intIndex), 10);
		this.Year = parseInt(strMonthYear.substring(intIndex + 1), 10);

		return this;
	},
	ParseMonthYear: function(strMonthYear)
	{
		var intIndex = strMonthYear.indexOf("/");
		this.Day = 1;
		this.Month = parseInt(strMonthYear.substring(0, intIndex), 10);
		this.Year = parseInt(strMonthYear.substring(intIndex + 1), 10);
	},
	ParseString: function(strDayMonthYear)
	{
		var dtCh = "/";
		var pos1 = strDayMonthYear.indexOf(dtCh);
		var pos2 = strDayMonthYear.indexOf(dtCh, pos1 + 1);
		this.Day = parseInt(strDayMonthYear.substring(0, pos1), 10);
		this.Month = parseInt(strDayMonthYear.substring(pos1 + 1, pos2), 10);
		this.Year = parseInt(strDayMonthYear.substring(pos2 + 1), 10);

		return this;
	},
	ParseDate: function(jsdate)
	{
		this.Day = jsdate.getDate();
		this.Month = jsdate.getMonth() + 1;
		this.Year = parseInt(jsdate.getFullYear(), 10);

		return this;
	},
	DaysInMonth: function()
	{
		var dd = new Date(this.Year, this.Month, 0);
		return dd.getDate();
	},
	//Is the current date between MinRange and MaxRange
	IsInRange: function()
	{
		if (this.MinRange == null && this.MaxRange == null)
		{
			return true;
		}
		else
		{
			if (this.MinRange == null || this.MinRange == "")
			{
				this.MinRange = 0;
			}

			if (this.MaxRange == null || this.MaxRange == "")
			{
				this.MaxRange = 0;
			}

			var intVal = this.convertToInt(this);
			var intMinOp = this.MinRange == 0 ? 0 : this.convertToInt(new Mondial.SimpleDate().ParseString(this.MinRange));
			var intMaxOp = this.MaxRange == 0 ? 0 : this.convertToInt(new Mondial.SimpleDate().ParseString(this.MaxRange));

			return (intVal >= intMinOp) && (intVal <= intMaxOp);
		}
	},
	//Is given date greater than current SimpleDate
	IsGreater: function(strDate2)
	{
		var intDate1 = this.convertToInt(this);
		var intDate2 = this.convertToInt(new Mondial.SimpleDate().ParseString(strDate2));

		return (intDate1 >= intDate2);
	},
	GetFullYear: function(year, century, cutoffyear)
	{
		return (year + parseInt(century)) - ((year < cutoffyear) ? 0 : 100);
	},
	convertToInt: function(simpleDate)
	{
		return simpleDate.GetDate().valueOf();
	},
	//Outputs the simple date in the format dd/MM/yyyy
	ToString: function()
	{
		return this.padDate(this.Day) + "/" + this.padDate(this.Month) + "/" + this.Year;
	}
});

Mondial.Quote = Class.create(
{
	Adults: 1,
	Dependants: 0,
	Destination: "WORLDWIDE",
	StartDate: "",
	EndDate: "",
	Selection: "",
	PromotionCode: "",
	AffiliateCode: "",

	///Prototype Init Function - Called when object created
	initialize: function()
	{

	}
});

Mondial.PlanControl = Class.create(
{
	SelectedPlan: null,
	Destination: "",
	Premium: 0.00,
	BenefitsLinkUrl: "",
	Destination: "WORLDWIDE",
	Blurb: "",
	OnBuyClick: null,

	///Prototype Init Function - Called when object created
	initialize: function(planSet, destination) {
		this.Id = "planControl" + planSet.Id;
		this.PlanSet = planSet;
		this.Destination = destination;

		this.BenefitsLinkUrl = this.PlanSet.Plans[0].BenefitsUrl + "?mode=inline";

		this.PremiumDiv = $(this.Id + "_premiumDiv");
		this.BlurbDiv = $(this.Id + "_blurbDiv");
		this.NameDiv = $(this.Id + "_nameDiv");
		this.BenefitsLink = $(this.Id + "_benefitsLink");
		this.BuyLink = $(this.Id + "_buyLink");
		this.BuyLinkDisabled = $(this.Id + "_buyLinkDisabled");
		this.MoreLink = $(this.Id + "_moreLink");
		this.MoreInfo = $(this.Id + "_moreInfo");
		this.NewDestination = destination;

		this.BuyLink.observe("click", this.buy_click.bind(this));
		this.setDestination(destination);
	},
	setPremium: function(premium) {
		if (premium == "0.00") {
			this.PremiumDiv.update("N/A");
			this.BuyLink.hide();
		}
		else if (IsDomestic(this.NewDestination) && this.SelectedPlan.Description.toUpperCase() == "BUDGET") {
			this.PremiumDiv.update("<span class='internationalOnly'>International Only</span>");
			this.BuyLink.hide();
			this.BuyLinkDisabled.show();
		}
		else {
			this.PremiumDiv.update("$" + premium);
			this.BuyLink.show();
			this.BuyLinkDisabled.hide();
			//new Effect.Highlight(this.PremiumDiv, { startcolor: '#FFFF61', endcolor: '#ffffff', restorecolor: 'transparent', keepBackgroundImage: true });
		}
	},
	setDestination: function(destination) {
		this.Destination = destination;
		var masterPlan = this.PlanSet;
		this.SelectedPlan = masterPlan.HasMultipleRegions ? this._findPlan(masterPlan, this.Destination) : masterPlan.Plans[0];
		this.NameDiv.update(this.SelectedPlan.Description);
		this.BlurbDiv.update(this.SelectedPlan.Blurb);
		this.BenefitsLink.href = this.SelectedPlan.BenefitsUrl;
	},
	getValidator: function(quoteControl, today, todayPlusOneYear, todayPlusTwoYears) {
		return new Mondial.QuoteValidator(quoteControl.StartDate, quoteControl.EndDate, new Mondial.SimpleDate().ParseString(today), new Mondial.SimpleDate().ParseString(todayPlusOneYear), new Mondial.SimpleDate().ParseString(todayPlusTwoYears), this.SelectedPlan.LengthLimit, Mondial.MapTimeUnit(this.SelectedPlan.LengthLimitTimeUnit));
	},
	setOnBuyClick: function(handler) {
		this.OnBuyClick = handler;
	},
	buy_click: function(e) {
		if (this.OnBuyClick != null) {
			this.OnBuyClick(e, this.PlanSet.Id);
		}
	},
	_findPlan: function(masterPlan, destination) {
		for (var i = 0; i < masterPlan.Plans.length; i++) {
			var childPlan = masterPlan.Plans[i];
			for (var j = 0; j < childPlan.Destinations.length; j++) {
				if (childPlan.Destinations[j].Code.toUpperCase() == destination.toUpperCase()) {
					return childPlan;
				}
			}
		}

		return null;
	}
});

Mondial.QuoteControl = Class.create(
{
	//Reference to event handler functions
	//OnDestinationChange: null,
	//OnAdultsChange: null,
	//OnChildrenChange: null,
	//OnStartDateChange: null,
	//OnEndDateChange: null,

	///Prototype Init Function - Called when object created
	initialize: function(destination, adults, children, startDay, startMonthYear, endDay, endMonthYear, startDate, endDate, initQuote, promotionCode, affiliateCode)
	{
		//Controls
		this.Destination = $(destination);
		this.Adults = $(adults);
		this.Children = $(children);
		this.StartDay = $(startDay);
		this.StartMonthYear = $(startMonthYear);
		this.EndDay = $(endDay);
		this.EndMonthYear = $(endMonthYear);
		this.StartDate = new Mondial.DMYControl(startDay, startMonthYear, initQuote != null ? initQuote.StartDate : startDate);
		this.EndDate = new Mondial.DMYControl(endDay, endMonthYear, initQuote != null ? initQuote.EndDate : endDate);
		this.InitialQuote = initQuote;
		this.PromotionCode = promotionCode;
		this.AffiliateCode = affiliateCode;
	},
	getQuote: function()
	{
		var quote = new Mondial.Quote();

		quote.Destination = this.Destination.options[this.Destination.selectedIndex == -1 ? 0 : this.Destination.selectedIndex].value;
		quote.Adults = this.Adults.options[this.Adults.selectedIndex == -1 ? 0 : this.Adults.selectedIndex].value;
		quote.Dependants = this.Children.options[this.Children.selectedIndex == -1 ? 0 : this.Children.selectedIndex].value;
		quote.StartDate = this.StartDay.value + '/' + this.StartMonthYear.value;
		quote.EndDate = this.EndDay.value + '/' + this.EndMonthYear.value;
		quote.AffiliateCode = this.AffiliateCode;
		quote.PromotionCode = this.PromotionCode;

		return quote;
	},
	loadStandard: function(masterPlans, destinations)
	{
		var dest = null;
		var adult = null;
		var child = null;
		if (this.Destination.options.length > 0)
		{
			dest = this.Destination.options[this.Destination.selectedIndex == -1 ? 0 : this.Destination.selectedIndex].value;
		}
		else
		{
			dest = this.InitialQuote.Destination;
		}
		if (this.Adults.options.length > 0)
		{
			adult = this.Adults.options[this.Adults.selectedIndex == -1 ? 0 : this.Adults.selectedIndex].value;
		}
		else
		{
			adult = this.InitialQuote.Adults;
		}
		if (this.Children.options.length > 0)
		{
			child = this.Children.options[this.Children.selectedIndex == -1 ? 0 : this.Children.selectedIndex].value;
		}
		else
		{
			child = this.InitialQuote.Dependants;
		}

		var maxAdults = masterPlans[0].MaxAdults;
		var maxDependants = masterPlans[0].MaxDependants;

		this.Adults.options.length = 0;
		this.Children.options.length = 0;

		for (var i = 0; i < maxAdults; i++)
		{
			this.Adults.options[i] = new Option(i + 1, i + 1);
		}
		for (var i = 0; i <= maxDependants; i++)
		{
			this.Children.options[i] = new Option(i, i);
		}
		this.Destination.options.length = 0; // clear list box

		for (i = 0; i < destinations.length; i++)
		{
			this.Destination.options[i] = new Option(destinations[i].Description, destinations[i].Code);
		}

		if (dest != null)
		{
			this.setDestination(dest);
		}

		if (adult != null)
		{
			this.setAdult(adult);
		}

		if (child != null)
		{
			this.setChild(child);
		}
	},
	clearEvents: function()
	{
		if (this.OnDestinationChange != null) Event.stopObserving(this.Destination, "change", this.OnDestinationChange);
		if (this.OnAdultsChange != null) Event.stopObserving(this.Adults, "change", this.OnAdultsChange);
		if (this.OnChildrenChange != null) Event.stopObserving(this.Children, "change", this.OnChildrenChange);
		if (this.OnStartDateChange != null) Event.stopObserving(this.StartDay, "change", this.OnStartDateChange);
		if (this.OnStartDateChange != null) Event.stopObserving(this.StartMonthYear, "change", this.OnStartDateChange);
		if (this.OnEndDateChange != null) Event.stopObserving(this.EndDay, "change", this.OnEndDateChange);
		if (this.OnEndDateChange != null) Event.stopObserving(this.EndMonthYear, "change", this.OnEndDateChange);

	},
	//Clears controls (does not clear start and end date)
	clearControls: function()
	{
		this.Destination.options.length = 0;
		this.Adults.options.length = 0;
		this.Children.options.length = 0;
},
	/*
	setOnDestinationChange: function(handler)
	{
		if (this.OnDestinationChange != null)
		{
			Event.stopObserving(this.Destination, "change", this.OnDestinationChange);
		}
		this.OnDestinationChange = handler;
		this.Destination.observe("change", handler);
	},
	setOnAdultsChange: function(handler)
	{
		if (this.OnAdultsChange != null)
		{
			Event.stopObserving(this.Adults, "change", this.OnAdultsChange);
		}
		this.OnAdultsChange = handler;
		this.Adults.observe("change", handler);
	},
	setOnChildrenChange: function(handler)
	{
		if (this.OnChildrenChange != null)
		{
			Event.stopObserving(this.Children, "change", this.OnChildrenChange);
		}
		this.OnChildrenChange = handler;
		this.Children.observe("change", handler);
	},
	setOnStartDateChange: function(handler)
	{
		if (this.OnStartDateChange != null)
		{
			Event.stopObserving(this.StartDay, "change", this.OnStartDateChange);
			Event.stopObserving(this.StartMonthYear, "change", this.OnStartDateChange);
		}
		this.OnStartDateChange = handler;
		this.StartDay.observe("change", handler);
		this.StartMonthYear.observe("change", handler);
	},
	setOnEndDateChange: function(handler)
	{
		if (this.OnEndDateChange != null)
		{
			Event.stopObserving(this.EndDay, "change", this.OnEndDateChange);
			Event.stopObserving(this.EndMonthYear, "change", this.OnEndDateChange);
		}
		this.OnEndDateChange = handler;
		this.EndDay.observe("change", handler);
		this.EndMonthYear.observe("change", handler);
	},
	*/
	setAdult: function(selected)
	{
		for (var i = 0; i < this.Adults.options.length; i++)
		{
			var option = this.Adults.options[i];
			if (option.value == selected)
			{
				option.selected = true;
			}
		}
	},
	setChild: function(selected)
	{
		for (var i = 0; i < this.Children.options.length; i++)
		{
			var option = this.Children.options[i];
			if (option.value == selected)
			{
				option.selected = true;
			}
		}
	},
	setDestination: function(selected)
	{
		for (var i = 0; i < this.Destination.options.length; i++)
		{
			var option = this.Destination.options[i];
			if (option.value.toUpperCase() == selected.toUpperCase())
			{
				option.selected = true;
			}
		}
	},
	setStartDate: function(startDate)
	{
		this.StartDate.updateDate(startDate);
	},
	setEndDate: function(endDate)
	{
		this.EndDate.updateDate(endDate);
	},
	getDestination: function()
	{
		return this.Destination.options[this.Destination.selectedIndex == -1 ? 0 : this.Destination.selectedIndex].value;
	}
});

Mondial.ErrorDisplayControl = Class.create(
{
  Container: null,
  Title: "Error",
  Items: {},
  Height: 31,
  ProcessingDisplay: null,

  ///Prototype Init Function - Called when object created
  initialize: function(container, processingDisplay)
  {
    this.Container = $(container);
    this.ProcessingDisplay = $(processingDisplay);
  },
  AppendAndDisplay: function(messages)
  {
    var errorTemplate1 = new Template('&#8226; #{message1}');
    var errorTemplate2 = new Template('1. #{message1}<br/>2. #{message2}');
    var errorTemplate3 = new Template('1. #{message1}<br/>2. #{message2}<br/>3. #{message3}');

    if (messages == null)
    {
      return;
    }
    if (typeof (messages) === 'string')
    {
      this.Container.update(errorTemplate1.evaluate({ message1: messages, title: this.Title }));
    }
    else if (messages.length == 1)
    {
      this.Container.update(errorTemplate1.evaluate({ message1: messages[0], title: this.Title }));
    }
    else if (messages.length == 2)
    {
      this.Container.update(errorTemplate2.evaluate({ message1: messages[0], message2: messages[1], title: this.Title }));
    }
    else
    {
      this.Container.update(errorTemplate3.evaluate({ message1: messages[0], message2: messages[1], message3: messages[2], title: this.Title }));
    }
    this.Display();
  },
  AppendAndDisplayWarning: function(messages)
  {
    var errorTemplate1 = new Template('&#8226; #{message1}');
    var errorTemplate2 = new Template('1. #{message1}<br/>2. #{message2}');
    var errorTemplate3 = new Template('1. #{message1}<br/>2. #{message2}<br/>3. #{message3}');

    if (typeof (messages) === 'string')
    {
      this.Container.update(errorTemplate1.evaluate({ message1: messages, title: "Please Note:" }));
    }
    else if (messages.length == 1)
    {
      this.Container.update(errorTemplate1.evaluate({ message1: messages[0], title: "Please Note:" }));
    }
    else if (messages.length == 2)
    {
      this.Container.update(errorTemplate2.evaluate({ message1: messages[0], message2: messages[1], title: "Please Note:" }));
    }
    else
    {
      this.Container.update(errorTemplate3.evaluate({ message1: messages[0], message2: messages[1], message3: messages[2], title: "Please Note:" }));
    }
    this.Display();
  },
  Display: function()
  {
    //this.Container.show();
    this.ProcessingDisplay.show();
  },
  Hide: function()
  {
    //this.Container.hide();
    this.ProcessingDisplay.hide();
  }
});

Mondial.Ajax.Request = Class.create(Ajax.Request,
{
	_request: null,
	_respondToReadyState: null,
	running: false,
	autoCancel: true,

	///Prototype Init Function - Called when object created
	initialize: function($super, options)
	{
		this._request = this.request;
		this._respondToReadyState = this.respondToReadyState;
		this.request = Prototype.emptyFunction;
		$super(options);

		this.respondToReadyState = (function(readyState)
		{
			this.running = false;
			this._respondToReadyState(readyState);
		});
	},
	send: function(url)
	{
		if (this.autoCancel) this.cancel();
		this.running = true;
		this._request(url);
	},
	cancel: function()
	{
		if (this.running)
		{
			this.running = false;
			this.transport.onreadystatechange = Prototype.emptyFunction;
			this.transport.abort();
		}
	}
});

Mondial.BaseService = Class.create(
{
	Request: null,
	RequestTimeout: 20, //Timeout in seconds
	aborted: false,
	Url: "",
	requestTimer: null,
	running: false,
	onComplete: null,
	onError: null,
	onStart: null,
	onNotFound: null,
	onTimeout: null,

	///Prototype Init Function - Called when object created
	initialize: function(url, onComplete, onError, onNotFound, onStart, onTimeout)
	{
		this.URL = url;
		this.onComplete = onComplete;
		this.onError = onError;
		this.onStart = onStart;
		this.onNotFound = onNotFound;
		this.onTimeout = onTimeout;
	},
	internalSubmit: function(url, method)
	{
		//If we have an existing request, abort it
		this.abortRequest();

		this.aborted = false;

		this.clearTimeout();

		//Make a call to the start function
		if (this.onStart) this.onStart();

		var modTime = "&MT=" + Math.random();

		this.setAbortRequestTimeout();

		this.Request = new Ajax.Request(url + modTime,
		{
			method: method,
			onSuccess: this.onSuccess.bind(this),
			on404: this.onNotFound.bind(this),
			onFailure: this.onError.bind(this)
		});
	},
	onException: function(e)
	{

	},
	abortRequest: function()
	{
		if (this.Request != null && this.Request.getStatus() != 200)
		{
			this.aborted = true;
			this.Request.transport.onreadystatechange = Prototype.emptyFunction;
			this.Request.transport.abort();
		}
	},
	clearTimeout: function()
	{
		if (this.requestTimer)
		{
			window.clearTimeout(this.requestTimer);
		}
	},
	onSuccess: function(response)
	{
		this.clearTimeout();
		if (this.aborted)
		{
			var timeout = this.onTimeout.bind(this);
			timeout(response);
		}
		else if (this.Request.success())
		{
			var complete = this.onComplete.bind(this);
			complete(response);
		}
	},
	setAbortRequestTimeout: function()
	{
		this.requestTimer = window.setTimeout((function() { this.abortRequest() }).bind(this), this.RequestTimeout * 1000);
	}
});

Mondial.StandardQuoteService = Class.create(Mondial.BaseService,
{
	CommandType: "QUOTE",
	Preview: false,
	///Prototype Init Function - Called when object created
	initialize: function($super, url, onComplete, onError, onNotFound, onStart, onTimeout)
	{
		$super(url, onComplete, onError, onNotFound, onStart, onTimeout);
	},
	Submit: function(noOfAdults, noOfDependants, destination, startDate, endDate, planSets, promotionCode, affiliateCode)
	{
		var planIDs = "";

		for (var i = 0; i < planSets.length; i++)
		{
			planIDs = planIDs + planSets[i].PlanSetId + ";";
		}

		var urlParams = "&A=" + noOfAdults + "&C=" + noOfDependants + "&R=" + destination + "&SD=" + startDate + "&ED=" + endDate + "&P=" + planIDs + "&promo=" + promotionCode + "&affiliate=" + affiliateCode + "&preview=" + this.Preview;

		this.internalSubmit(this.URL + "?op=" + this.CommandType + urlParams, 'GET');
	}
});

var DomUtils =
{
	removeChildElements: function(c)
	{
		while (c.hasChildNodes())
		{
			c.removeChild(c.firstChild);
		}
	},
	appendChild: function(parent, elm, id)
	{
		if (Prototype.Browser.IE)
		{
			//Workaround bug in IE
			var y = document.createElement('div');
			y.id = id;
			y.innerHTML = elm.outerHTML;
			parent.appendChild(y);
		}
		else
		{
			parent.appendChild(elm);
		}
	},
	appendChildren: function(parent, elements, id)
	{
		if (Prototype.Browser.IE)
		{
			//Workaround bug in IE
			var y = document.createElement('div');
			y.id = id;
			elements.each(function(elm)
			{
				y.innerHTML = y.innerHTML + elm.outerHTML;
			});
			parent.appendChild(y);
		}
		else
		{
			elements.each(function(elm)
			{
				parent.appendChild(elm);
			});
		}
	},
	createPNGFixedStyle: function(imgURL, style)
	{
		return Mondial.ApplyPNGFix ? style + "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + imgURL + "', sizingMethod='scale');background-image:none;" : style;
	}
};

var CookieUtil =
{
	//Functions from http://www.quirksmode.org/js/cookies.html
	createCookie: function(name, value, days)
	{
		if (days)
		{
			var date = new Date();
			date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
			var expires = "; expires=" + date.toGMTString();
		}
		else var expires = "";

		document.cookie = name + "=" + value + expires + "; path=/";
	},
	readCookie: function(name)
	{
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for (var i = 0; i < ca.length; i++)
		{
			var c = ca[i];
			while (c.charAt(0) == ' ') c = c.substring(1, c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
		}
		return null;
	},
	eraseCookie: function(name)
	{
		this.createCookie(name, "", -1);
	}
};

function getCookieDate(firstDate, secondDate, today)
{
	var dteStart = new Mondial.SimpleDate().ParseString(secondDate);

	if (!dteStart.IsGreater(today)) {
		return firstDate;
	}

	return secondDate;
}

function validateCookieDates(startDate, endDate)
{
	try
	{
		return new Mondial.SimpleDate().ParseString(endDate).IsGreater(startDate);
	}
	catch (e)
	{
		return false;
	}
}

Mondial.QuoteCookie = Class.create(Mondial.Quote,
{
	Mode: Mondial.QUOTE_MODE_SAB,
	SliderState: null,
	initialize: function($super, quote) {
		$super();
		if (quote != null) {
			this.Update(quote);
		}
	},
	Update: function(quote) {
		this.Adults = quote.Adults;
		this.Dependants = quote.Dependants;
		this.Destination = quote.Destination;
		this.StartDate = quote.StartDate;
		this.EndDate = quote.EndDate;
		if (quote.Selection != null && quote.Selection != "") {
			this.Selection = quote.Selection;
		}
		if (quote.Mode != null) {
			this.Mode = quote.Mode;
		}
		if (quote.SliderState != null) {
			this.SliderState = quote.SliderState;
		}
	}
});

Mondial.CookieHandler = Class.create(
{
	initialize: function()
	{


	},
	load: function()
	{
		var content = CookieUtil.readCookie(Mondial.SAB_COOKIE_NAME);
		if (content != null)
		{
			var quoteCookie = new Mondial.QuoteCookie();
			var obj = unescape(content).evalJSON(true);
			quoteCookie.Update(obj);
			return quoteCookie;
		}
		return null;
	},
	save: function(quoteCookie)
	{
		var jsonQuote = escape(Object.toJSON(quoteCookie));
		CookieUtil.createCookie(Mondial.SAB_COOKIE_NAME, jsonQuote);
	}
});
