/*--------------------------------------------------------------------------*
 * 
 * Copyright (C) 2009-2011 Brand Labs LLC
 * 
 *--------------------------------------------------------------------------*/

var CruiseItinerarySelection = Class.create({
	COOKIE_NAME: 'CruiseSelection',
	WARNING_COOKIE_NAME: 'ShortDepartureWarning',
	MAXIMUM_NUMBER_OF_NIGHTS: 30,
	MINIMUM_TIME_BEFORE_SHIP_DEPARTURE: 259200000 /* 72 hours in milliseconds */,
	DEFAULT_SELECT_LINE: 'Select Cruise Line',
	DEFAULT_SELECT_SHIP: 'Select Ship',
	HOTEL_LINE: 'Hotel',
	OTHER_LINE: 'Other',
	GET_LINES_URL: '/v/cruises/ajax-data/cruise-lines.json.asp',
	GET_SHIPS_URL: '/v/cruises/ajax-data/cruise-ships.json.asp',
	SUBMIT_ORDER_IMG_SRC: '/v/vspfiles/templates/ShoreEx/images/buttons/btn_1pagec_placeorder.gif',
	EXPEDITE_FEE_PRODUCTCODE: 'EXPEDITE',
	EXPEDITE_FEE_PRODUCT_OPTION_NAME: 'SELECT___EXPEDITE___1592',
	EXPEDITE_FEE_PRODUCT_OPTION_VALUE: '19595',
	EXPEDITE_FEE_MESSAGE: 'NOTE: Our deadline for booking excursions is 3 days prior to your cruise. If you choose to proceed, a $25 Expedite Fee will be added to your order.',
	EXPEDITE_FEE_SUCCESS_MESSAGE: 'The expedite fee has been added to your cart.',
	EXPEDITE_FEE_FAILURE_MESSAGE: 'The expedite fee could not be added to cart, this may cause your order to not be processed. Please contact our support at 866-999-6590 during normal business hours (Mon-Fri, 9am-6pm EST)',
	
	initialize: function(lineElement, shipElement, arrivalElement, nightsElement) {
		this.options = $H(arguments[4] || {});
		
		//Verify something is available
		if(lineElement == null || Object.isUndefined(lineElement)) {
			return;	
		}
		if(shipElement == null || Object.isUndefined(shipElement)) {
			return;	
		}
		if(arrivalElement == null || Object.isUndefined(arrivalElement)) {
			return;	
		}
		if(nightsElement == null || Object.isUndefined(nightsElement)) {
			return;	
		}
		
		this.lineElement = lineElement;
		this.shipElement = shipElement;
		this.arrivalElement = arrivalElement;
		this.nightsElement = nightsElement;
		
		//Load the default values
		this.defaults = unescape(getCookieValue(this.COOKIE_NAME));
		//Parse, if error set to null
		try {
			this.defaults = this.defaults.evalJSON(true);
		}
		catch(e){
			this.defaults = null;
		}
		if(this.defaults == null) {
			this.defaults = {};
		}
		
		//Setup date picker
		this.arrivalDatePicker = new DatePicker({
			relative : this.arrivalElement.identify(),
			keepFieldEmpty: false,
			language: 'en',
			topOffset: 0,
			cellCallback: this.change.bind(this),
			dateFilter: DatePickerUtils.noDatesBefore(0),
			zindex: 9000
		});
		this.arrivalElement.writeAttribute('readonly', 'readonly');
		this.arrivalElement.writeAttribute('value', this.defaults.arrival || '');
		
		//Fill nights with values
		$R(1, this.MAXIMUM_NUMBER_OF_NIGHTS).each(function(value){
			var options = new Hash({value: value});
			if((this.defaults.nights || '') == value) {
				options.set('selected', 'selected');
			}
			this.nightsElement.insert({bottom: new Element('option', options.toObject()).update(value + (value == 1 ? ' Night' : ' Nights')	)});
		}.bind(this));
		
		//Monitor when elements change
		Event.observe(this.lineElement, 'change', this.change.bind(this));
		Event.observe(this.shipElement, 'change', this.change.bind(this));
		Event.observe(this.arrivalElement, 'change', this.change.bind(this));
		Event.observe(this.nightsElement, 'change', this.change.bind(this));
		
		//Monitor form submission
		Event.observe(this.lineElement.up('form'), 'submit', this.validateSubmission.bindAsEventListener(this));
				
		//Start by loading the available lines
		this.getLines();
	},
	
	change: function() {
		//Store selections in a cookie
		addCookie(this.COOKIE_NAME, Object.toJSON({
			lineId: this.lineElement.getValue(),
			lineName: (this.lineElement.selectedIndex < 0) ? '' : this.lineElement.options[this.lineElement.selectedIndex].text,
			shipId: this.shipElement.getValue(),
			shipName: (this.shipElement.selectedIndex < 0) ? '' : this.shipElement.options[this.shipElement.selectedIndex].text,
			arrival: this.arrivalElement.getValue(),
			nights: this.nightsElement.getValue()
		}));
	},	
	
	getLines: function() {
		this.lineElement.writeAttribute('disabled', 'disabled');
		this.lineElement.disabled = true;
		
		new Ajax.Request(this.GET_LINES_URL, {
			method: 'get',			
			encoding: 'utf-8',
			evalJS: false,
			sanitizeJSON: true,
			
			onSuccess: this.populate.bind(this, this.lineElement, this.DEFAULT_SELECT_LINE, (this.defaults.lineId || null)),
			onComplete: function() {
				var hotelElement = new Element('option', {value: '-1'});
				var otherElement = new Element('option', {value: '-2'});
				
				if(this.options.get('alternateLines') == true) {
					//Select default
					if ((this.defaults.lineId || '') == '-1') {
						hotelElement.writeAttribute('selected', 'selected');
					}
					else if ((this.defaults.lineId || '') == '-2') {
						otherElement.writeAttribute('selected', 'selected');
					}
					
					//Put content within element
					hotelElement.update(this.HOTEL_LINE)
					otherElement.update(this.OTHER_LINE)
					
					//Add extra available fields
					this.lineElement.insert({bottom: hotelElement});
					this.lineElement.insert({bottom: otherElement});
				}
			}.bind(this)
		});
		
		//Update ships when line changes
		Event.observe(this.lineElement, 'change', function(){
			try {
				this.getShips(this.lineElement.options[this.lineElement.selectedIndex].value);
			}
			catch(e){/*Ignore*/}
		}.bind(this));
		
		//Load defaults
		if((this.defaults.lineId || null) != null) {
			this.getShips(this.defaults.lineId);
		}
	},
	
	getShips: function(lineId) {
		this.shipElement.writeAttribute('disabled', 'disabled');
		this.shipElement.disabled = true;
		
		//Nothing selected
		if(new String(lineId).empty()) {
			this.populate(this.shipElement, this.DEFAULT_SELECT_SHIP, null, {responseJSON: []});
			return;
		}
		
		//Special where no ship is needed
		if(!new String(lineId).empty() && (lineId == -1 || lineId == -2)) {			
			this.populate(this.shipElement, this.DEFAULT_SELECT_SHIP, 0 /*Special one will be selected*/, {responseJSON: [{shipId: 0, name: 'None'}]});
			this.change(); //Need this trigger since "None" is default selected
			return;
		}
		
		new Ajax.Request(this.GET_SHIPS_URL, {
			method: 'get',			
			encoding: 'utf-8',
			evalJS: false,
			sanitizeJSON: false,
			parameters: {lineid: lineId},
			
			onSuccess: this.populate.bind(this, this.shipElement, this.DEFAULT_SELECT_SHIP, (this.defaults.shipId || null))
		});		
	},
	
	populate: function(element, defaultLabel, selectedId, transport) {
		var data = null;
		var options = null;
		
		try {		
			if(transport == null || transport.responseJSON == null) {
				return;
			}
			
			//Remove everything in the select
			element.update('');
			
			//Add available options in select
			data = $A(transport.responseJSON);
			
			//If nothing selected, use first one
			options = $H({value: ''});
			if(selectedId == null) {
				options.set('selected', 'selected');
			}
			
			element.insert({bottom: new Element('option', options.toObject()).update(defaultLabel)});
			data.each(function(item){
				var id = (Object.isUndefined(item.lineId) ? item.shipId : item.lineId);
				
				//Selected item
				options = $H({value: id});
				if(selectedId == id) {
					options.set('selected', 'selected');
				}				
				
				element.insert({bottom: new Element('option', options.toObject()).update(item.name)});
			}.bind(this));
		
			//Enable the element
			element.writeAttribute('disabled');
			element.disabled = false;	
		}
		catch(e){/*Ignore*/}		
	},
	
	expediteFeeRequired: function(departureDateString, minimumTime) {
		var slashifiedDepartureDateString = null;
		var departureDate = null;
		var today = new Date().valueOf();
		var diff = 0;	
		
		/*Only bother on the checkout page*/
		if (window.location.pathname.toLowerCase() != 'one-page-checkout.asp') {
			return false;
		}
		
		try {
			/*Date string must be in american slash date format for IE*/
			if (departureDateString.indexOf('-') != -1) {
				var parts = departureDateString.split('-');
				slashifiedDepartureDateString = parts[1]+ "/" + parts[2]  + "/" + parts[0];
			} else {
				slashifiedDepartureDateString = departureDateString;
			}
			
			departureDate = Date.parse(slashifiedDepartureDateString);
			
			/* Calculate diff */
			diff = parseInt(departureDate) - parseInt(today);
		} catch(e) {/*Ignore*/}

		/* Does the given departure date require an expedite fee? */
		return (diff <= minimumTime)							
	},
	
	checkCartAndAddExpediteFee: function() {
		new Ajax.Request('/ajaxcart.asp', {
			method: 'get',
			evalJSON: true,
			sanitizeJSON: true,
			onComplete: function(transport) {
				var addExpediteFee = true;
				try {
					/*If the ajax cart returned, check if it's in the cart*/
					if (transport.status == 200) {
						var cartJSON = transport.responseText.evalJSON();
						cartJSON.Products.each(function(cartItem) {
							if (addExpediteFee) {
								addExpediteFee = (cartItem.ProductCode.toLowerCase() != this.EXPEDITE_FEE_PRODUCTCODE.toLowerCase())
							}
						}.bind(this));
					}
				} catch(e) {/*Ignore*/}
				
				/* Add expedite fee if missing */
				if (addExpediteFee) {
					if (confirm(this.EXPEDITE_FEE_MESSAGE)) {
						this.addExpediteFeeToCart();
					} 
				} else {
					this.manualFormSubmission();
				}
			}.bind(this)
		});
	},
	
	addExpediteFeeToCart: function() {
		var params = new Hash();
		params.set(this.EXPEDITE_FEE_PRODUCT_OPTION_NAME, this.EXPEDITE_FEE_PRODUCT_OPTION_VALUE);
		params.set('productcode', this.EXPEDITE_FEE_PRODUCTCODE);
		params.set('returnto', '/shoppingcart.asp');
		params.set('replacecartid', '');
		params.set('e', '');
		params.set('btnaddtocart.x', 0);
		params.set('btnaddtocart.y', 0);
		
		new Ajax.Request('/productdetails.asp?productcode=' + this.EXPEDITE_FEE_PRODUCTCODE, {
			method: 'post',
			evalJSON: false,
			sanitizeJSON: false,
			parameters: params,
			onSuccess: function(transport) {
				alert(this.EXPEDITE_FEE_SUCCESS_MESSAGE);
				
				this.manualFormSubmission();
			}.bind(this), 
			onFailure: function(transport) {
				alert(this.EXPEDITE_FEE_FAILURE_MESSAGE);
				
				this.manualFormSubmission();
			}.bind(this)
		});
	},
	
	/**
	 * Handle form submission.
	 * Any changes here may need to be reflected in checkout.js or itinerary-validator.js
	 * @param {Object} event
	 */
	validateSubmission: function(event) {
		Event.stop(event);
		
		if (event.target == null || Object.isUndefined(event.target)) {
			return;
		}
		
		//this.lineElement
		if (this.lineElement == null || Object.isUndefined(this.lineElement) || this.lineElement.selectedIndex == 0) {
			alert('Please select a Cruise Line.');
			return;
		} 
		//this.shipElement
		if (this.shipElement == null || Object.isUndefined(this.shipElement) || this.shipElement.selectedIndex == 0) {
			alert('Please select a Ship.');
			return;
		} 
		//this.arrivalElement (which is actually cruise departure date)
		if (this.arrivalElement == null || Object.isUndefined(this.arrivalElement) || this.arrivalElement.value.blank()) {
			alert('Please select a Departure Date.');
			return;
		} else if (!doesCookieExist(this.COOKIE_NAME) || !doesCookieExist(this.WARNING_COOKIE_NAME) 
		|| (getCookieValue(this.WARNING_COOKIE_NAME) != new Date(this.arrivalElement.value).valueOf())) {			
			//Issue warning
			if (this.expediteFeeRequired(this.arrivalElement.value, this.MINIMUM_TIME_BEFORE_SHIP_DEPARTURE)) {
				/* Issue warning, add fee to cart */
				this.checkCartAndAddExpediteFee(event);
			} else { 
				/* No date issue, submit */
				this.manualFormSubmission();
			}
		}
	},
	
	manualFormSubmission: function() {
		this.lineElement.up('form').submit();
	}
});
