// 
//  crown-core.js
//  Crown Core JavaScript
//  
//  Created by Victor Nguyen on 2009-08-12.
//  Copyright 2009 igloo digital. All rights reserved.
// 

// Firebug Debug
// ********************
// REMOVE IN PRODUCTION
// ********************
if (!("console" in window) || !("firebug" in console)) {
   var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group",
     "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"
   ];
   window.console = {};
   for (var i = 0; i < names.length; ++i) {
   	window.console[names[i]] = function() {};
   }
}

// setting up namespace
var Crown = {};


// common methods that execute on all pages
Crown.Common = {
	
	init: function() {
		Crown.Common.InputDefaults.init();
		Crown.Common.FormImageButtons.init();
		Crown.Common.Tabs.init();
		Crown.Common.ColumnedPages.init();
		Crown.Common.GenericForm.init();
	},
	
	isEmpty: function (value) {
	  return value === null || value === undefined || value === '';
	},
	
	
	// Sets default values for input text fields
	InputDefaults: {
		
		TRIGGER_CLASS: 'has_default',
		
		init: function () {
			$('input.'+Crown.Common.InputDefaults.TRIGGER_CLASS+'[title]').each(function(){
				var field = $(this);
				var defaulttext = field.attr('title');
				Crown.Common.InputDefaults._setDefaultText(field, defaulttext);
				field.blur(function(){ Crown.Common.InputDefaults._setDefaultText(field, defaulttext); });
				field.focus(function(){ Crown.Common.InputDefaults._removeDefaultText(field, defaulttext); });
			});
		},
		
		_removeDefaultText: function (el, defaulttext) {
			var currentvalue = el.attr('value');
			if (currentvalue == defaulttext) {
				el.attr({value: ''});
			};
		},
		
		_setDefaultText: function (el, defaulttext) {
			var currentvalue = el.attr('value');
			if (Crown.Common.isEmpty(currentvalue)) {
				el.attr({value: defaulttext});
			}
		}
		
	},
	
	// Enables image hovers on all input[image] buttons
	// Any input[image] image will need to have an accompaning image for the hover state
	// Example:
	// image-filename.gif
	// image-filename-over.gif
	FormImageButtons: {
		
		IMAGES_DIR: '/library/images/',
		OVERIMAGE_SUFFIX: '-over',
		
		init: function () {
			var imagesubmits = $('input[type="image"]');
			// using .hover event somtimes doesn't register mouseout for some reason
			imagesubmits.mouseover(
				function(){
					$(this).attr({rel: this.src});
					this.src=Crown.Common.FormImageButtons.IMAGES_DIR + Crown.Common.FormImageButtons._getOverImage($(this));
				}
			);
			imagesubmits.mouseout(
				function(){
					this.src= $(this).attr('rel');
				}
			);
		},
		
		_getOverImage: function (el) {
			var src = el.attr('src');
			var filename = String(src.split('/').slice(-1));
			var imagename = String(filename.split('.').slice(0, -1)) + Crown.Common.FormImageButtons.OVERIMAGE_SUFFIX;
			var imageext = String(filename.split('.').slice(-1));
			filename = imagename + '.' + imageext;
			return filename;
		}
		
	},
	
	
	// Sets up tabbed content
	// tab's a[href] needs to correspond with the id of the panel it should activate
	// Example:
	// <a href="#victorisawesome">
	// <div id="victorisawesome">
	Tabs: {
		
		TABSWRAPPER_CLASS: 'tabs_group', // element that wraps only the tab <a> elements (e.g. the <ul> or a wrapping <div>)
		
		init: function () {
			$('.'+Crown.Common.Tabs.TABSWRAPPER_CLASS).click(function(e){
				if ($(e.target).is('a')) {
					Crown.Common.Tabs._handleClick($(e.target));
					return false;
				}
			});
		},
		
		_handleClick: function (el) {
			Crown.Common.Tabs._displayClickedPanel(el);
			Crown.Common.Tabs._displayClickedTab(el);
		},
		
		_displayClickedPanel: function (clicked_tab) {
			var corresponding_panel = $(clicked_tab.attr('href'));
			var related_panels = $('.'+corresponding_panel.attr('class').split(' '));
			related_panels.hide();
			corresponding_panel.show();
		},
		
		_displayClickedTab: function (clicked_tab) {
			var parent = clicked_tab.parents('.'+this.TABSWRAPPER_CLASS); // go up the tree to get tab group
			var related_tabs = parent.find('a');
			
			related_tabs.removeClass('active');
			clicked_tab.addClass('active');
			
			// related_tabs.stop().removeAttr('style').removeClass('active');
			// clicked_tab.addClass('active',200);
			// Animating addClass() doesn't work in IE6. Thanks, Microsoft.
			// Apparently, animating classes is flakey in IE. Seems to have been addressed and will be in the next general release of jqueryui
			// http://groups.google.com/group/jquery-ui-dev/browse_thread/thread/b165405b979775ed
		}

	},
	
	
	// Ajax behaviour for item browsers in Dining, Shopping, Bars and Casino sections
	// Initialised from section-specific JS
	Browser: {
		
		ActiveRequest: null,
		
		init: function (list_id, replaceme_id, url) {
			var links = Crown.Common.Browser._getLinks(list_id);
			links.click(function(){
				var clicked_link = $(this);
				var venue_param = clicked_link.attr('rel');
				if (Crown.Common.isEmpty(venue_param)) { return true; } // if rel attr not set, go to standard a[href] link instead
				if (Crown.Common.Browser.ActiveRequest) { Crown.Common.Browser.ActiveRequest.abort(); }
				Crown.Common.Browser.ActiveRequest = $.ajax({
				  url: url + venue_param,
				  cache: false,
				  success: function(html){
						Crown.Common.Browser._resetActiveClass(links, clicked_link);
				    $('#' + replaceme_id).replaceWith(html);
				  }
				});
				return false;
			});
		},
		
		_getLinks: function (list) {
			return $('#' + list).find('a');
		},

		_resetActiveClass: function (list, el) {
			list.removeClass('active');
			el.addClass('active');
		}
		
	},
	
	
	// Hotel Booking Widget
	// Initialised from crown-homepage.js and crown-hotels.js
	HotelBooking: {
		
		BOOKINGFORM_CLASS: 'form_hotel_booking',
		FIELDSTOSEND_CLASS: 'ihoteler_param', // form fields to send to ihotelier
		DATEFIELD_VISIBLE_CLASS: 'form_hotel_datepicker', // visible date field that inits datepicker
		DATEFIELD_PARAM_CLASS: 'form_hotel_dateparam', // hidden input field to send date in accepted format to ihotelier
		HOTELFIELD_ID: 'home_form_hotel_hotel',
		
		init: function () {
			if ($('.' + Crown.Common.HotelBooking.BOOKINGFORM_CLASS).val() == null) { return false; }
			this.BookingForm.init();
			this.DatePicker.init();
		},
		
		BookingForm: {			
			init: function () {
				var booking_form = $('.'+Crown.Common.HotelBooking.BOOKINGFORM_CLASS);
				booking_form.submit(function(){
					window.open(Crown.Common.HotelBooking.BookingForm._genHotelBookingURL());
					return false;
				});
			},
			
			_genHotelBookingURL: function () {
				var url = $('#' + Crown.Common.HotelBooking.HOTELFIELD_ID).val();
				// serialize only fields with .ihotelier-param class
				var query_string = $('.'+Crown.Common.HotelBooking.BOOKINGFORM_CLASS+' .'+Crown.Common.HotelBooking.FIELDSTOSEND_CLASS).fieldSerialize();
				url = url + '&' + query_string;
				return url;
			}
		},
		
		DatePicker: {
			INITIALDATE_US: null,
			INITIALDATE_AU: null,
			
			SERVERDATE_ID: 'crown_server_date',
			
			TODAY_SERVER: {
				DATE: null,
				MON: null,
				YEAR: null
			},
			
			MONTH_NAMES: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			DAY_NAMES: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
			
			init: function () {
				if ($('#' + Crown.Common.HotelBooking.DatePicker.SERVERDATE_ID).val() == null) { return false; }
				
				var date_field = $('input.'+Crown.Common.HotelBooking.DATEFIELD_VISIBLE_CLASS);
				var date_param = $('input.'+Crown.Common.HotelBooking.DATEFIELD_PARAM_CLASS);

				this._setTodayFromServer();
				this._genCurrentDates();

				date_field.datepicker({
					// for whatever reason, manually setting defaultDate to server-served date does not stop the highlighting of the client's current date ...
					// to compensate for this, i am currently overwriting the highlight css style in /library/css/datepicker/styles.css to look like the default state ...
					defaultDate: this._getCurrentDateObject(),
					// dateFormat: 'dd/mm/yy',
					dateFormat: 'DD, d M yy',
					showAnim: 'slideDown',
					duration: 250,
					firstDay: 1,
					minDate: this._getCurrentDateObject(),
					altField: date_param, // set date in ihotelier (US) format to hidden input value
					altFormat: 'mm/dd/yy',
					constrainInput: true
				});
				
				// Manually setting inital date values for DatePicker as defaultDate option doesn't seem to work ...
				// date_field.attr({value: Crown.Common.HotelBooking.DatePicker.INITIALDATE_AU});
				date_field.attr({value: Crown.Common.HotelBooking.DatePicker._getFormattedDateFromDateObj(this._getCurrentDateObject())});
				date_param.attr({value: Crown.Common.HotelBooking.DatePicker.INITIALDATE_US});
			},
			
			_getFormattedDateFromDateObj: function (dateobj) {
				var day = Crown.Common.HotelBooking.DatePicker.DAY_NAMES[dateobj.getDay()];
				var date = dateobj.getDate();
				var mon = Crown.Common.HotelBooking.DatePicker.MONTH_NAMES[dateobj.getMonth()];
				var year = dateobj.getFullYear();
				return day + ', ' + date + ' ' + mon + ' ' + year;
			},
			
			_setTodayFromServer: function () {
				var server_date = $('#' + Crown.Common.HotelBooking.DatePicker.SERVERDATE_ID).attr('value');
				Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.DATE = server_date.split('/')[0];
				Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.MON = parseInt(server_date.split('/')[1], 10);
				Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.YEAR = server_date.split('/')[2];
			},
			
			_genCurrentDates: function () {
				var date = Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.DATE;
				date = (date < 10) ? '0' + date : date;
				var mon = Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.MON;
				mon = (mon < 10) ? '0' + mon : mon;
				var year = Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.YEAR;
				this.INITIALDATE_US = mon+'/'+date+'/'+year;
				this.INITIALDATE_AU = date+'/'+mon+'/'+year;
			},
			
			_getCurrentDateObject: function () {
				return new Date(Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.YEAR, Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.MON - 1, Crown.Common.HotelBooking.DatePicker.TODAY_SERVER.DATE);
			}
		}
		
	},
	
	// Common Flash values
	Flash: {
		
		MIN_VERSION: '9.0.0',
		EXPRESSINSTALL_PATH: '/library/flash/expressInstall.swf',
		NOFLASH_HTML: '<p>This content requires the latest Adobe Flash Player.</p><a href="http://www.adobe.com/go/getflashplayer" target="_blank">Download it for free!</a>',
		
		// swbobject embed callback, displays no Flash message if embed was unsuccessful
		embedCallBack: function (e) {
			if (e.success == false) {
				$('#' + e.id).html(Crown.Common.Flash.NOFLASH_HTML);
			}
		}
		
	},
	
	// Adjusts the padding of columns in multi-column pages with dynamic headings
	// Because the server-generated <h1>'s can be of any height, we'll adjust the
	// right column accordingly so it lines up with the left column.
	// This is messy - but, to maintain document structure integrity, necessary ... mmmmm, hacky
	ColumnedPages: {
		
		PAGETEMPLATE_CLASSES: ['page_item_category', 'page_generic_subnav'],
		PageTemplateObj: null,
		
		init: function () {			
			// assign PageTemplateObj to matching body element, if it exists
			for (var i=0; i < this.PAGETEMPLATE_CLASSES.length; i++) {
				var template = $('body.' + this.PAGETEMPLATE_CLASSES[i]);
				if (template.length != 0) {
					Crown.Common.ColumnedPages.PageTemplateObj = template;
					break;
				}
			};
			
			if (this.PageTemplateObj) {
				// console.log('template matches');
				this._offsetRightColumn();
			} else {
				return false;				
			}
		},
		
		_offsetRightColumn: function () {
			var left_gap, right_gap, offset;
			
			// gap to keyline in left col ...offset for border-bottom on this element
			left_gap = $('h1').outerHeight() - 1; 
			
			// generate the offset padding required on right col
			var h2 = this._getSubHeading();
			if (h2) {
				// ... if a h2 exists, it's the difference in height between h1 and h2
				right_gap = h2.outerHeight();
				offset = this._getOffsetPadding(left_gap, right_gap);
			} else {
				// ... when no h2 exists, it's the same as left_gap
				offset = left_gap;
			}
			
			$('.col_right').css({'padding-top': offset + 'px'});
		},
		
		_getSubHeading: function () {
			var h2 = this.PageTemplateObj.find('.col_right').find('h2');
			if ((h2.length > 0) && (h2.parent('.generic_rich_text').length == 0)) {
				// console.log('sub heading!');
				return h2;
			} else {
				// console.log('no sub heading, padding used to bring keyline down');
				return false;
			}
		},
		
		_getOffsetPadding: function (left_gap, right_gap) {
			if (left_gap > right_gap) {
				return (left_gap - right_gap);
			} else {
				return 0;
			}
		}
		
	},
	
	
	// Initialises validation for forms
	// Uses jquery.validate plugin
	GenericForm: {
		
		CLASS: 'generic_form',
		
		init: function () {
			var form = $('.' + Crown.Common.GenericForm.CLASS);
			if (form.length == 0) return false;
			form.validate();
		}
		
	},
	
	
	// Generic cookie handling functions courtesty of quirksmode.org
	Cookies: {
		
		create: 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=/";
		},

		read: 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;
		},

		erase: function (name) {
			this.create(name,"",-1);
		}
		
	}
	
};


// on domready
$(document).ready(function(){
	Crown.Common.init();
});