/**
	Source: tk_widget.js
		This script creates a widget in an <iframe> element.
	Build: 2.2.13394
	Copyright (c) 2005-2010 TreKnowledge Technologies Inc., All rights reserved.
*/

/**
	Global constants
*/

// 'country' option values:
var TK_CANADA = 'ca',
	TK_USA    = 'us';

// 'externalLinkTarget' option values:
var TK_NEW_WINDOW     = 1,
	TK_CURRENT_WINDOW = 2;

// 'language' option values:
var TK_ENGLISH = 'en',
	TK_FRENCH  = 'fr',
	TK_SPANISH = 'es';

// 'navigation' option values:
var TK_DESTINATION = 1,
	TK_THEME       = 2;

// 'thumbnailCreation' option values:
var TK_BEST_FIT   = 'b',
	TK_EXACT_SIZE = 'x',
	TK_MAX_HEIGHT = 'h',
	TK_MAX_WIDTH  = 'w';

// 'thumbnailEffect' option values:
var TK_NO_EFFECT       = '',
	TK_POLAROID        = 'nt',
	TK_RANDOM_TILT     = 'rt',
	TK_TILT_LEFT       = 'tl',
	TK_TILT_RIGHT      = 'tr',
	TK_ROUNDED_CORNERS = 'rc';

// 'thumbnailPosition' option values:
var TK_LEFT  = 'l',
	TK_RIGHT = 'r';

// 'type' option values:
var TK_ACCOMMODATION_AD_BTN  = 'aca-b',
	TK_ACCOMMODATION_AD_LIST = 'aca-l',
	TK_ATTRACTION_AD_BTN     = 'ata-b',
	TK_ATTRACTION_AD_LIST    = 'ata-l',
	TK_ACCOMMODATION_SEARCH  = 'acs-b';

(function() {
	// List of supported widget dimensions.
	var widgetDims = [
		'120x240','120x600','125x125','160x600','180x150','200x200','234x60',
		'250x250','300x200','300x250','336x280','336x85','468x60','728x90'];

	for (var i=0,l=widgetDims.length; i <= l; i++) {
		var dim = widgetDims[i];
		window['TK_ACCOMMODATION_AD_BTN_'+dim]  = TK_ACCOMMODATION_AD_BTN+'-'+dim;
		window['TK_ACCOMMODATION_AD_LIST_'+dim] = TK_ACCOMMODATION_AD_LIST+'-'+dim;
		window['TK_ACCOMMODATION_SEARCH_'+dim]  = TK_ACCOMMODATION_SEARCH+'-'+dim;
		window['TK_ATTRACTION_AD_BTN_'+dim]     = TK_ATTRACTION_AD_BTN+'-'+dim;
		window['TK_ATTRACTION_AD_LIST_'+dim]    = TK_ATTRACTION_AD_LIST+'-'+dim;	
	}
})();

/**
*/
(function() {
	// Constants
	var BUTTON = 'b', LIST = 'l';
	var OID_REGX = /^(\d{16,20})$/;

	/**
		List of supported widget dimensions.
	*/
	var STD_DIMENSIONS = {
		'120x240': [120, 240], // Vertical Banner
		'120x600': [120, 600], // Skyscraper
		'125x125': [125, 125], // Button
		'160x600': [160, 600], // Wide skyscraper
		'180x150': [180, 150], // Small Rectangle
		'200x200': [200, 200], // Small Square
		'234x60':  [234, 60],  // Half Banner
		'250x250': [250, 250], // Square
		'300x200': [300, 200], // Small Rectangle
		'300x250': [300, 250], // Rectangle
		'336x280': [336, 280], // Large Rectangle
		'336x85':  [336, 85],  // Large Button (custom to TNY)
		'468x60':  [468, 60],  // Banner
		'728x90':  [728, 90]   // Leaderboard
	};

	/**
		Options:
			--- APPLICATION OPTIONS ---
			baseUrl - string, optional - URL prefix to use for communicating
				with the service. The default is the base URL used to call the
				launcher script (i.e. tk_widget.js).
			channel - integer, required - Channel identifier
			country - string, required - 2-letter ISO country code
			debug - boolean, optional - Enable/disable the debugging mode. Adds
				extra comments in the source code of the widget. The default is
				false.
			destination - string, optional - Destinatin identifier.
			language - string, optional - 2-letter ISO language code.
				Possible values:
					'en' - English (default)
					'es' - Spanish
					'fr' - French
			externalLink - string, optional - More information URL.
			externalLinkTarget - integer, optional - Indicates how to handle the
				externalLink option:
					1 - open in a new window (default)
					2 - open in the current window
			navigation - integer, optional - Navigation method.
				Possible values:
					1 - by destination
					2 - by theme (default)
			packageLength - array, optional - Package length expressed in
				number of days and nights. The default is null (i.e. server
				defined).
				Examples:
					[2, 2] = 2 days, 2 nights
					[3, 2] = 3 days, 2 nights
			searchType - integer, optional - Identifies the type of search
				algorithm to use.
				Possible values:
					1 - Next best deal
					2 - Within a 50km radious of the specified destination
			searchOffset - integer, optional - Show next availability starting
				in N days from now. The default is null (i.e. server defined).
			sessionId - string, required - Session identifier.
			theme - string, optional - Theme identifier. The default is null.

			--- FORMAT/STYLING OPTIONS ---
			cssFile - string, optional - Reference to a custom CSS file.
			descriptionLength - integer, optional - Maximim length of the
				description text.
			height - integer/string, optional - Custom height value in pixels.
			itemsPerPage - integer, optional - Number of items to display. The
				default is 3.
			loadingImage - string, optional - Image to display while the
				widget is loading. The default is to not display an image.
			type - string, optional - Widget type and size.
				Format: <item type>-<widget type>[-<widget dimensions>]
				Possible values for ...
					<content type>:
						'aca' - Accommodation ads
						'acs' - Accommodation search
						'ata' - Attraction ads
					<widget type>:
						'b' - Button
						'l' - List
					<widget dimensions> (optional)
						'160x600' - 160 px in width by 600 px in height
						'200x200' -
						'336x85'  -
			width - integer - Custom width value in pixels.

			--- THUMBNAIL OPTIONS ---
			noThumbnails - boolean, optional - Show / hide thumbnails. The
				default is 0 (false).
			thumbnailCreation - string, optional - Thumbnail generation method.
				Possible values:
					'b' / 'bestFit'   - Best fit (default)
					'h' / 'maxHeight' - Max height
					'w' / 'maxWidth'  - Max width
					'x' / 'exactSize' - Exact size
			thumbnailEffect - string, optional - Visual effect to be applied to
				the thumbnails. Available effects:
					'' / null - Apply no effects (default). Display the
						thumbnail as is. Only CSS styling is applied.
					'nt' / 'polaroid' - Polaroid style photo with no tilting
					'rt' / 'randomTilt' - Polaroid style photo with random
						tilting
					'tl' / 'tiltLeft' - Polaroid style photo with left tilt
					'tr' / 'tiltRight' - Polaroid style photo with right tilt
					'rc' / 'roundedcorners' - Round all 4 corners with a radius
						of 8.
					'rc:NN:ABCD' / 'roundedcorners:NN:ABCD'
						NN - Custom radius in pixels.
						ABCD - Corner selection. A sequence of 4 bits (0,1)
							identifying the corners to round (1) and not to
							round (0).
								A=top left corner
								B=top right corner
								C=bottom left corner
								D=bottom right corner
			thumbnailHeight - integer, optional - Maximum thumbnail height in
				pixels. The default is 64.
			thumbnailPosition - string, optional - Indicates where on the widget
				the thumbnail should appear. This options only applies to
				widgets that display a thumbnail and a description side by side.
				Possible values:
					'a' / 'alt'   - Alternate
					'l' / 'left'  - Left (default)
					'r' / 'right' - Right
			thumbnailWidth - integer, optional - Maximum thumbnail width in pixels.
				The default is 100.
			useThumbFrameBgImg - boolean, default: false - Indicates whether to use
				a background image (supplied in a custom CSS) for thumbnails.
				Setting it to true, overrides the thumbnailEffect option.
	*/
	var OPTIONS = [
		'baseUrl','channel','country','cssFile','debug','descriptionLength',
		'destination','externalLink','externalLinkTarget','height','language',
		'itemsPerPage','loadingImage','navigation','noThumbnails',
		'packageLength','purpose','searchType','searchOffset','sessionId',
		'theme','thumbnailCreation','thumbnailEffect','thumbnailHeight',
		'thumbnailPosition','thumbnailWidth','type','useThumbFrameBgImg','width'
	];

	/**
	*/
	function createWidget(oOpts) {
		var div, iframe, 
			ua    = navigator.userAgent.toLowerCase(),
			isIE6 = /msie 6/.test(ua) && !/opera/.test(ua),
			url   = oOpts.baseUrl+'/tk_widget.php?'+createQueryString(oOpts);

		div = document.createElement('div');
		div.id                       = 'tkWidgetWrapper_'+window.TkWidgetCount;
		div.className                = 'tkWidgetWrapper';
		div.style.backgroundImage    = 'url('+(oOpts.loadingImage || 'none')+')';
		div.style.backgroundPosition = '50%';
		div.style.backgroundRepeat   = 'no-repeat';
		div.style.height             = oOpts.height+'px';
		div.style.width              = oOpts.width+'px';
		
		iframe = document.createElement('iframe');
		iframe.id                    = 'tkWidgetFrame_'+window.TkWidgetCount;
		iframe.className             = 'tkWidgetFrame';
		iframe.allowTransparency     = 'true';
		iframe.frameBorder           = 0;
		iframe.hspace                = 0;
		iframe.marginHeight          = 0;
		iframe.marginWidth           = 0;
		iframe.scrolling             = 'no';
		iframe.src                   = (isIE6 ? 'about:blank' : url);
		iframe.style.display         = 'block';
		iframe.style.height          = oOpts.height+'px';
		iframe.style.overflow        = 'visible';
		iframe.style.width           = oOpts.width+'px';
		iframe.vspace                = 0;

		div.appendChild(iframe);

		// Delay setting the src attribute so the rest of page has the time to
		// load. Set the delay as multiples of 300ms.
		if (isIE6) {
			setTimeout(function() {iframe.src = url}, window.TkWidgetCount * 300);
		}

		return div;
	};

	/**
	*/
	function createQueryString(oOpts) {
		var params = {
			baseUrl:       oOpts.baseUrl,
			channel:       oOpts.channel,
			country:       oOpts.country,
			cssFile:       oOpts.cssFile,
			debug:         oOpts.debug ? 1 : 0,
			descLength:    oOpts.descriptionLength,
			dest:          oOpts.destination,
			extLink:       oOpts.externalLink,
			extTarget:     oOpts.externalLinkTarget,
			height:        oOpts.height,
			itemsPerPg:    oOpts.itemsPerPage,
			lang:          oOpts.language,
			launch:        1,
			nav:           oOpts.navigation,
			noThumbs:      oOpts.noThumbnails ? 1 : 0,
			pkgLength:     oOpts.packageLength,
			searchOffset:  oOpts.searchOffset,
			searchType:    oOpts.searchType,
			session:       oOpts.sessionId,
			purpose:       oOpts.purpose,
			theme:         oOpts.theme,
			thumbCreation: oOpts.thumbnailCreation,
			thumbFx:       oOpts.thumbnailEffect,
			thumbHeight:   oOpts.thumbnailHeight,
			thumbPos:      oOpts.thumbnailPosition,
			thumbWidth:    oOpts.thumbnailWidth,
			type:          oOpts.type,
			useThumbBg:    oOpts.useThumbFrameBgImg ? 1 : 0,
			width:         oOpts.width
		};

		var queryStr = [];
		for (var name in params) {
			var value = params[name];
			if (value !== null) {
				queryStr.push(name+'='+encodeURIComponent(value));
			}
		}

		return queryStr.join('&')+'&time='+(new Date().getTime());
	};

	/**
		Returns:
			object - Collection of filtered options. All unknown options are
			dropped.
	*/
	function filterOptions(oOpts) {
		var filtered = {};
		for (var i=0, l=OPTIONS.length; i < l; i++) {
			var name = OPTIONS[i], value = oOpts[name];
			filtered[name] = (value === undefined ? null : value);
		}
		return filtered;
	};

	/**
	*/
	function getThisScriptElement() {
		var scripts = document.getElementsByTagName('script');
		return scripts[scripts.length-1];
	};

	/**
	*/
	function isArray(o) {
		return Object.prototype.toString.call(o) === '[object Array]'
	};

	/**
	*/
	function isString(o) {
		return typeof o === 'string';
	};

	/**
	*/
	function pad(sValue, nLength, sPadChar) {
		sValue = ''+sValue;
		sPadChar = (sPadChar || '0');
		while (sValue.length < nLength) {
			sValue = sPadChar + sValue;
		}
		return sValue;
	};

	/**
	*/
	function parseOptions(oOpts, sBaseUrl) {
		var bits, dims, height, val, width;

		oOpts = filterOptions(oOpts);

		// [START] Check mandatory options
		if (!pickInt(oOpts.channel, null)) {
			alert("TkWidget Error: Option 'channel' is either missing or invalid.");
			return false;
		}

		if (!pickOID(oOpts.sessionId, null)) {
			alert("TkWidget Error: Option 'sessionId' is either missing or invalid.");
			return false;
		}

		if (!oOpts.type || !isString(oOpts.type) || oOpts.type.length < 4) {
			alert("TkWidget Error: Option 'type' is either missing or invalid.");
			return false;
		}
		// [END]

		oOpts.baseUrl            = pickString(oOpts.baseUrl, sBaseUrl);
		oOpts.channel            = pad(oOpts.channel, 3, '0');
		oOpts.country            = pickString(oOpts.country, null, 2);
		oOpts.cssFile            = pickString(oOpts.cssFile, null);
		oOpts.debug              = !!oOpts.debug;
		oOpts.descriptionLength  = pickInt(oOpts.descriptionLength, null);
		oOpts.destination        = pickString(oOpts.destination, null);
		oOpts.externalLink       = pickString(oOpts.externalLink, null);
		oOpts.externalLinkTarget = pickInt(oOpts.externalLinkTarget, null);

		// format: <widget purpose>-<widget type>[-<widget dimensions>]
		bits = oOpts.type.split('-');
		oOpts.purpose = bits[0];
		oOpts.type    = (bits[1] == BUTTON ? BUTTON : LIST);
		width = height = 200;
		if (bits.length == 3) {
			dims = STD_DIMENSIONS[bits[2]];
			if (dims) {
				height = dims[1];
				width  = dims[0];
			}
		}
		oOpts.height = pickInt(oOpts.height, height);
		oOpts.width  = pickInt(oOpts.width, width);

		if (oOpts.type == BUTTON) {
			oOpts.itemsPerPage = 1;
			oOpts.searchOffset = pickInt(oOpts.searchOffset, null);
		}
		else {
			oOpts.itemsPerPage = pickInt(oOpts.itemsPerPage, 3);
			oOpts.searchOffset = null;
		}

		oOpts.language     = pickString(oOpts.language, null, 2);
		oOpts.loadingImage = pickString(oOpts.loadingImage, null);
		oOpts.navigation   = pickInt(oOpts.navigation, 2);

		oOpts.noThumbnails = !!oOpts.noThumbnails;
		if (oOpts.noThumbnails) {
			oOpts.thumbnailCreation  = null;
			oOpts.thumbnailEffect    = null;
			oOpts.thumbnailHeight    = null;
			oOpts.thumbnailPosition  = null;
			oOpts.thumbnailWidth     = null;
			oOpts.useThumbFrameBgImg = null;
		}
		else {
			val = (oOpts.thumbnailCreation || '-').toLowerCase().charAt(0);
			oOpts.thumbnailCreation = ('bhwx'.indexOf(val) > -1 ? val : null);

			oOpts.thumbnailHeight = pickInt(oOpts.thumbnailHeight, null);
			oOpts.thumbnailWidth  = pickInt(oOpts.thumbnailWidth, null);

			oOpts.useThumbFrameBgImg = !!oOpts.useThumbFrameBgImg;
			if (oOpts.useThumbFrameBgImg) {
				oOpts.thumbnailEffect = null;
			}
			else {
				val = (oOpts.thumbnailEffect || '').toLowerCase();
				switch (val) {
					case 'nt': case 'notilt':
						val = 'nt'; break;
					case 'rt': case 'randomtilt':
						val = 'rt'; break;
					case 'tl': case 'tiltleft':
						val = 'tl'; break;
					case 'tr': case 'tiltright':
						val = 'tr'; break;
					case 'rc': case 'roundedcorners':
						val = 'rc'; break;
					default:
						if (isString(val) && val.length) {
							var parts = val.split(':');
							if (parts[0] == 'roundedcorners' || parts[0] == 'rc') {
								val = 'rc'+parts[1];
								if (parts.length === 3) {
									val += ':'+parts[2];
								}
							}
							else {
								val = null;
							}
						}
						else {
							val = null;
						}
				}
				oOpts.thumbnailEffect = val;
			}

			val = (oOpts.thumbnailPosition || '-').toLowerCase().charAt(0);
			oOpts.thumbnailPosition = ('alr'.indexOf(val) > -1 ? val : null);
		}

		if (isArray(oOpts.packageLength) &&
			oOpts.packageLength[0] >= 0 &&
			oOpts.packageLength[1] >= 0) {
			oOpts.packageLength = oOpts.packageLength.join(',');
		}
		else {
			oOpts.packageLength = null;
		}

		oOpts.searchType = pickInt(oOpts.searchType, null);
		oOpts.theme      = pickOID(oOpts.theme, null);

		return oOpts;
	};

	/**
	*/
	function pickInt(nValue, nDefault) {
		nValue = parseInt(nValue, 10);
		return isNaN(nValue) ? nDefault : nValue;
	};

	/**
	*/
	function pickOID(nValue, nDefault) {
		return (nValue || '').match(OID_REGX) ? nValue : nDefault;
	};

	/**
	*/
	function pickString(sValue, sDefault, nLength) {
		if (isString(sValue) && sValue.length) {
			return nLength ?
				(sValue.length === nLength ? sValue : sDefault) : sValue;
		}
		return sDefault;
	};

	if (window.TkWidgetCount === undefined) {
		// Initialize the instance counter
		window.TkWidgetCount = 0;

		// Identify the base URL of the widget
		var src = getThisScriptElement().src;
		window.TkWidgetBaseUrl = src.substring(0, src.indexOf('/apps/')+5);
	}

	/**
	*/
	window.TkWidget = function(oOptions, oContainer) {
		TkWidgetCount++;
		var options = parseOptions(oOptions, TkWidgetBaseUrl);
		if (options) {
			var widget = createWidget(options);
			// If oContainer is defined, append the new widget to oContainer;
			// otherwise, insert it after this script element.
			(oContainer || getThisScriptElement().parentNode).appendChild(widget);
		}
	}
})();
