// Common Javascript

/**
 * Initialize all common class and common method
 */
var Common = new Class( {
	
	Implements: Options,
		
	options: {
		Class: ['GLOBALS', 'CookieManager', 'Dictionary', 'RX', 'Redirect', 'Rewrite', 'Cache', 'CurrencyService', 'Contact', 'Help']
	},
	
	initialize: function() {
		this.autoload();
	},
	
	autoload: function() {
		// Init class
		this.options.Class.each( function( Class ) {
			eval( Class + " = new " + Class );
		} );
	},
	
	setGlobalCursor: function( type ) {
		document.body.setStyle( 'cursor', type );
	},
	
	toObject: function( queryString ) {
		var obj = {};
		this.query = queryString.split( '&' );
		for( var i = 0; i < this.query.length; i++ ) {
		    var tmp = this.query[i].split( '=' );
		    if( tmp[0] == '' )
		    	continue;
		    if( !tmp[1] ) {
		        tmp[1] = true;
		    } else if( tmp[1] == 'false' ) {
		        tmp[1] = false;
		    } else if( tmp[1] == 'true' ) {
		        tmp[1] = true;
		    }
		    obj[tmp[0]] = tmp[1];
		}
		return obj;
	},
	
	truncate: function( s, l, trunc ) {
		var str = '';
		var l_str = s.length;
		var l_trunc = ( $type( trunc ) != false ) ? trunc.length : 0;
		
		if( l_str > l + l_trunc ) {
			str = s.substr( 0, l - l_trunc );
			if( $type( trunc ) != false ) str = str + trunc;
			return str;
		} else {
			return s;
		}
	},
	
	round: function( n, l, full ) {
		var num = '';
		var n = n.toFloat();
		num = n.round( l ).toString();
		if( full == true || $type( full ) == false ) {
			var m = num.match( /\.([0-9]+)/ );
			if( m != null ) {
				var d = l - m[1].length;
				if( d > 0 ) {
					for( var i = 0; i < d; i++ ) {
						num += '0';
					}
				}
			}
		}
		return num;
	},
	
	random: function( array ) {
		
		return array.sort( ( function() { return Math.round( Math.random() );} ) );
		
	},
	
	toggleLoader: function( params ) {
		
		var el = params.el;
		var name = params.name;
		var options = {
			elements : {
				loader : {
					'class' : 'loading_full'
				}
			}
		};
		if( $type( params.element ) == 'element' )
			options.elements.loader.element = params.element;
		
		if( $type( WBAnimation ) == 'class' ) {
			var name = 'loader' + name;
			if( $type( params.state ) != false )
				$GLOBALS[name].state = params.state;
			
			if( $type( $GLOBALS[name] ) == false ) {
				$GLOBALS[name] = new WBAnimation( options );  
				$GLOBALS[name].render();
				$GLOBALS[name].state = false;
			}
			if( $GLOBALS[name].state == false ) {
				$GLOBALS[name].state = true;
				$GLOBALS[name].showLoader( el );			
			} else {
				$GLOBALS[name].state = false;
				$GLOBALS[name].hideLoader();
			}
		}
		
		// By default scroll element to top
		if( $type( $(el) ) != false && params.scroll2top == true ) $(el).scrollTo( 0, 0 );
		
	},
	
	sort: function( object, params ) {

		if( $type( object.json ) == 'object' && $type( object.sub_obj ) != false ) {
			var json = object.json[object.sub_obj];
		} else {
			return false;
		}

		var field = ( $type( params.field ) != false ) ? params.field : 'id';
		var type =( $type( params.type ) != false ) ? params.type : 'string';
		var order =( $type( params.order ) != false ) ? params.order : 'asc';
		
		var json_length = json.length;
		for( var i = 0; i < json_length; i++ ) {
			for( var j = 0; j < json_length; j++ ) {
				if( this.setSortable( json[i][field], type ) < this.setSortable( json[j][field], type ) ) {
					var tmp = json[i];
					json[i] = json[j];
					json[j] = tmp;
				}
			}
		}

		if( order == 'desc' ) json.reverse();

		object.json[object.sub_obj] = json;
		
		return object.json;
		
	},
	
	setSortable: function( value, type ) {
		
		switch( type ) {
			case 'int':
				value = value.toInt();
				break;
			case 'float':
				value = value.toFloat();
				break;
			case 'time':
				value = value.replace(/:/,"").toInt();
				break;
			case 'string':
			default:
				value = value;
				break;
		}
		
		return value;
		
	},
	
	center: function( el, dynamic ) {
	
		el.setStyles( {
			top: window.getSize().y / 2 + window.getScroll().y - el.getSize().y / 2,
			left: window.getSize().x / 2 + window.getScroll().x - el.getSize().x / 2
		} );
		
		if( $type( dynamic ) != false && dynamic == true ) {
			window.addEvents( {
				scroll: function() {
					Common.center( el, false );
				},
				resize: function() {
					Common.center( el, false );
				}
			} );
		}
		
	},
	
	scrollTo: function( mixed ) {
		
		if( $type( this.scollWindow ) == false )
			this.scrollWindow = new Fx.Scroll( window );
		
		if( $type( mixed ) == 'element' || ( $type( mixed ) == 'string' && $type( $(mixed) ) == 'element' ) )
			this.scrollWindow.toElement( mixed );
		else if( $type( mixed ) == 'object' )
			this.scrollWindow.set( mixed.x, mixed.y );
		else if( $type( mixed ) == 'string' )
			this.scrollWindow['to' + mixed.capitalize()]();
			
	},
	
	blinking: function( element, options ) {
		
		if( $type( options ) == false ) options = {};
		
		var colorFrom = options.colorFrom || '#FFCC66';
		var colorTo = options.colorTo || '#FFFFFF';
		var howMany = options.howMany || 5;
		
		this.blink = new Fx.Tween( element, {
			fps: 30,
			link: 'chain',
			duration: 200
		} );
		for( var i = 0; i < howMany; i++ ) {
			this.blink.start( 'background-color', colorTo, colorFrom );
			this.blink.start( 'background-color', colorFrom, colorTo );
		}
		
	},
	
	toggleDisplay: function( ele, force ) {
		
		var force = ( $type( force ) == false ) ? null : force;
		
		if( force != null ) {
			$(ele).setStyle( 'display', ( force == true ? 'block' : 'none' ) );
			return;
		}
		
		if( $(ele).getStyle( 'display' ) == 'none' )
			$(ele).setStyle( 'display', 'block' );
		else
			$(ele).setStyle( 'display', 'none' );
		
	}
	
} );

/**
 * Set a var to global with $GLOBALS like php
 */
var GLOBALS = new Class( {
	
	Implements: Options,
	
	options: {
		// Global options
	},
	
	initialize: function() {
		$GLOBALS = new Array();
	}

} );

var Cache = new Class( {
	
	Implements: Options,
	
	options: {
		// Cache options
	},
	
	initialize: function() {
		$GLOBALS['Cache'] = new Array();
	},
	
	set: function( item, key ) {
		$GLOBALS['Cache'][key] = item;
	},
	
	get: function( key ) {
		return $GLOBALS['Cache'][key];
	},
	
	del: function( key ) {
		delete $GLOBALS['Cache'][key];
	}
	
} );

/*
 * Extends Request.JSON for use cache
 */
var JSONCache = new Class( {

    Extends: Request.JSON,

    get: function( options, key ) {
	
		this.key = key;
		if( !Cache.get( this.key ) )
			this.parent( options );
		else {
			this.fireEvent( 'request' );
			this.success( JSON.encode( Cache.get( this.key ) ) );
		}
		
    },
	
	success: function( text ) {
    	
		if( !Cache.get( this.key ) ) {
			this.response.json = JSON.decode( text, this.options.secure );
			Cache.set( this.response.json, this.key );
			this.onSuccess( this.response.json, text );
		} else {
			this.onSuccess( JSON.decode( text, this.options.secure ), text );
		}
			
	}

} );

/*
 * Extends Cookie for write specific cookie
 */
var CookieManager = new Class( {
	
	Implements: Options,
	
	options: {
		// Cookie options
		path: '/',
		duration: 365,
		secure: false
	},
	
	initialize: function() {
		
		this.options.domain = window.location.href.match( /http\:\/\/(.*?)\/.*$/ )[1].replace( 'www', '' );
		
	},
	
	get: function( name ) {
	
		return Cookie.read( name );
	
	},
	
	set: function( item, options ) {
		
		var $this = this;
		
		if( $type( options ) == 'object' ) {
			// save current options
			var cOptions = this.options;
			this.setOptions( options );
		}

		if( $type( item ) == 'object' ) {
			new Hash( item ).each( function( value, key ) {
				if( $type( value ) != false ) {
					Cookie.write( key, value, $this.options );
				}
			} );
			// reset options
			this.setOptions( cOptions );
			return true;
		} else {
			return false;
		}
	
	},
	
	remove: function( mixed ) {
		
		var $this = this;
		
		if( $type( mixed ) == 'string' ) {
			Cookie.dispose( mixed );
		} else if( $type( mixed ) == 'array' ) {
			mixed.each( function( el ) {
				Cookie.dispose( el );
			} );
		} else {
			return false;
		}
		
	}
	
} );

var RX = new Class( {
	
	Implements: Options,
	
	options: {
		// RX uri
		uri: '/rx/',
		// RX Params
		params: {
			origin: null,
			destination: null,
			lang: 'en',
			airline: null,
			depDate: null,
			retDate: null,
			//passengers: 18,
			currency: 'EUR',
			p: null,
			product: 'beta.travel',
			channel: null,
			sourceURL: null,
			test: false
		}
	},
	
	initialize: function() {
		var params = {
			origin: CookieManager.get( 'origin' ) || null,
			destination: CookieManager.get( 'destination' ) || null,
			lang: CookieManager.get( 'lang' ) || 'en',
			currency: CookieManager.get( 'currency' ) || 'EUR',
			p: CookieManager.get( 'p' ) || null,
			sourceURL: window.location.href.match( /http\:\/\/.*?(\/.*?)$/ )[1]
		};
		this.setOptions( {params: params} );
	},
	
	set: function( params ) {
		this.setOptions( {params: params} );
	},

	get: function() {
		return this.options.uri + '?' + Hash.toQueryString( this.options.params );
	}
	
} );

var Redirect = new Class( {
	
	Implements: Options,
	
	options: {
		site: 'beta',
		link: {
			beta: {
				host: 'http://beta.travel',
				base: '/?page={page}&origin={origin}&destination={destination}&oneway={oneway}&lang={lang}',
				depDate: '&depDate={depDate}',
				retDate: '&retDate={retDate}'
			},
			whichbudget: {
				host: 'http://www.whichbudget.com',
				base: '/routes.php?from={origin}&to={destination}'
			}
		},
		params: {
			page: 'Routes',
			origin: null,
			destination: null,
			originText: null,
			destinationText: null,
			depDate: null,
			retDate: null,
			oneway: false,
			lang: 'en',
			p: null
		}
	},
	
	initialize: function() {
		this.uri = new Array();
		this.options.params.lang = CookieManager.get( 'lang' ) || 'en';
	},
	
	getParam: function( param ) {
		if( $type( this.options.params[param] ) != false )
			return this.options.params[param];
		else
			return null;
	},
	
	setSite: function( site ) {
		this.options.site = site;
	},
	
	getSite: function() {
		return this.options.site;
	},

	set: function( params ) {
		this.setOptions( {params: params} );
		CookieManager.set( {
			origin: this.options.params.origin,
			destination: this.options.params.destination
		} );
	},
	getRemote : function( page ){
		return this.uri[page] ;
	},
	get: function( page ) {
		this.uri[page] = this.options.link[this.getSite()].host;
		
		// whichbudget options
		if( this.getSite() == 'whichbudget' ) {
			/* Doing that thru ajax to avoid double maintanence of WB links' structure on BT and WB domains
			 * if( this.getParam( 'lang' ) != 'en' ) this.uri[page] += '/' + this.getParam( 'lang' );
			 */
			$this = this ;
			new Request.JSON({url: "/cmd/?cmd=GetWBLink", onSuccess: function(response){
			   $this.uri[page] += response.uri ;
			// Adding partner ID
			if( $this.getParam( 'p' ) != null ){ 
				$this.uri[page] += '?p=' + $this.getParam( 'p' );
			}
			}}).get( $this.options.params  );
		}
		
		// beta options
		if( this.getSite() == 'beta' ) {
			
			this.uri[page] += this.options.link[this.getSite()].base.substitute( this.options.params );
			
			if( this.getParam( 'depDate' ) != null ) this.uri[page] += this.options.link[this.getSite()].depDate.substitute( this.options.params );
			if( this.getParam( 'retDate' ) != null ) this.uri[page] += this.options.link[this.getSite()].retDate.substitute( this.options.params );
		
			// Adding partner ID
			if( this.getParam( 'p' ) != null ) this.uri[page] += '&p=' + this.getParam( 'p' );
			
			// hasPrices false redirection
			if( this.getParam( 'hasPrices' ) != null ) this.uri[page] += '&hasPrices=' + this.getParam( 'hasPrices' );

		}
		return this.uri[page];
	},
	
	go: function( page, target ) {
		this.setOptions( {params: {page: page}} );
		
		// Rewrite if enabled
		if( Rewrite.enabled() == true ){
			var url = Rewrite.convert( this.options.params );			
			if( this.getSite() == 'whichbudget'){
				url = this.options.link.whichbudget.host + url ;
			}
			if( this.getParam( 'p' )){ 
				url += (url.indexOf('?') != -1 ? '&' : '?') + 'p=' + this.getParam( 'p' );
			}
		}else
			var url = this.get( page );

		switch( target ) {
			case '_blank':
				window.open( url );
				break;
			case '_parent':
				parent.window.location.href =url;
				break;
			default:
				document.location.href = url;
				break;
		}
	}
	
} );


var Rewrite = new Class( {
	
	Implements: Options,
	
	options: {
		RewriteEngine: true,
		extension: '.html',
		Routes: {
			pattern: '/routes/{origin}{destination}/{verbose}{extension}'
		},
		Prices: {
			// oneway
			patternow: '/cheapflights/{origin}{destination}/o/{verbose}{extension}',
			patternow_dd: '/cheapflights/{origin}{destination}/{depDate}/{verbose}{extension}',
			// return
			patternrt: '/cheapflights/{origin}{destination}/{verbose}{extension}',
			patternrt_dd: '/cheapflights/{origin}{destination}/d{depDate}/{verbose}{extension}',
			patternrt_rd: '/cheapflights/{origin}{destination}/r{retDate}/{verbose}{extension}',
			patternrt_dd_rd: '/cheapflights/{origin}{destination}/{depDate}-{retDate}/{verbose}{extension}'
		}
	},
	
	convert: function( params ) {
		
		var url = null;
		/*
		 * pattern basename
		 * after add letters options
		 * ow: oneway
		 * rt: return
		 * dd: depDate
		 * rd: retDate
		 */
		var pattern = 'pattern';
		var pattern_options = new Array();
		switch( params.page ) {
			case 'Prices':
				var obj = {};
				obj.lang = params.lang;
				obj.origin = params.origin;
				obj.destination = params.destination;
				obj.originText = params.originText.replace( / \(.*/, '' );
				obj.destinationText = params.destinationText.replace( / \(.*/, '' );
				
				obj.oneway = params.oneway;
				if( obj.oneway == true ) pattern_options[0] = 'ow';
				else pattern_options[0] = 'rt';
				obj.depDate = params.depDate || null;
				if( obj.depDate != null ) pattern_options[1] = 'dd';
				obj.retDate = params.retDate || null;
				if( obj.retDate != null ) pattern_options[2] = 'rd';
				
				if( obj.depDate != null )
					obj.month = $GLOBALS['months'][Date.parse(obj.depDate).getMonth()];
				else if( obj.depDate == null && obj.retDate != null )
					obj.month = $GLOBALS['months'][Date.parse(obj.retDate).getMonth()];
				else if( obj.depDate == null && obj.retDate == null )
					obj.month = null;
				
				if( obj.month == null )
					var verbose = _d( 'CHEAP FLIGHTS FROM TO' ).replace( /%1\$s/, '{originText}' ).replace( /%2\$s/, '{destinationText}' );
				else
					var verbose = _d( 'CHEAP FLIGHTS FROM TO IN' ).replace( /%1\$s/, '{originText}' ).replace( /%2\$s/, '{destinationText}' ).replace( /%3\$s/, '{month}' );
				obj.verbose = this.prepare( verbose.substitute( obj ) );
				
				obj.extension = this.options.extension;
				
				pattern = pattern + pattern_options.join( '_' ).replace( /__/g, '_' );
				var tpl = this.options.Prices[pattern];
				if( obj.lang != 'en' ) tpl = '/{lang}' + tpl;
				
				var url = tpl.substitute( obj );
				
				break;
			case 'Routes' :
				var obj = {};
				obj.lang = params.lang;
				obj.origin = params.origin;
				obj.destination = params.destination;
				obj.originText = params.originText.replace( / \(.*/, '' );
				obj.destinationText = params.destinationText.replace( / \(.*/, '' );
				var verbose = _d( 'CHEAP FLIGHTS FROM TO' ).replace( /%1\$s/, '{originText}' ).replace( /%2\$s/, '{destinationText}' );
				obj.verbose = this.prepare( verbose.substitute( obj ) );
				
				obj.extension = this.options.extension;
				
				pattern = pattern + pattern_options.join( '_' ).replace( /__/g, '_' );
				var tpl = this.options.Routes[pattern];
				if( obj.lang != 'en' ) tpl = '/{lang}' + tpl;
				
				var url = tpl.substitute( obj );
				
				break;
		}

		return url;
		
	},
	
	prepare: function( str ) {
		
        str = str.replace( /\/|'|\(|\)|,|:|"/g, ' ' );
        str = str.replace( /( ){2,}/g, ' ' );
        str = str.replace( /( )/g, '-' );
        str = str.replace( /-{2,}/g, '-' );
        str = str.toLowerCase();
        
        return str;
	},
	
	enabled: function() {
		return this.options.RewriteEngine;
	}

} );

/**
 * Set translation with Dictionary like Class Dictionary
 */
var Dictionary = new Class( {
	
	Implements: Options,

	options: {
		// Dictionary options
	},
	
	initialize: function() {
		$Dictionary = new Array();
	},
	
	set: function( key, value ) {
		$Dictionary[key] = value;
	},
	
	get: function( key ) {
		if( typeof( $Dictionary[key] ) == 'undefined' )
			return null;
		else
			return $Dictionary[key];
	}

} );
// Shortcut for use Dictionary easy
var _s = function( k, v ) {
	Dictionary.set( k, v );
};
var _d = function( k ) {
	return Dictionary.get( k );
};

var CurrencyService = new Class( {
	
	Implements: Options,
	
	options: {
		selected: null,
		class_select: 'cur_select',
		button: 'cur_div',
		dom: 'active_currency',
		list: 'currency_list',
		cur: '.currency',
		open: false
	},
	
	initialize: function() {
		
		var $this = this;
			window.addEvent( 'domready', function() {
				
				if( $type( $($this.options.button) ) != false ) {
					$($this.options.button).addEvent( 'click', function() {
						$this.toggle();
						$this.build();
					} );
				}
				
			} );
		this.options.selected = CookieManager.get( 'currency' ) || 'EUR';
	},
	
	show: function() {
		$(this.options.list).setStyle( 'visibility', 'visible' );
		this.options.open = true;
	},

	hide: function() {
		$(this.options.list).setStyle( 'visibility', 'hidden' );
		this.options.open = false;
	},
	
	toggle: function() {
		if( this.options.open == true )
			this.hide();
		else
			this.show();
	},
	
	set: function( cur ) {
		$(this.options.selected).removeClass( this.options.class_select );
		this.options.selected = cur;
		$(this.options.dom).set( 'text', cur );
		CookieManager.set( {currency: cur} );
		$(this.options.selected).addClass( this.options.class_select );
		window.fireEvent( 'changeCurrency' );
		this.hide();
	},
	
	get: function() {
		return this.options.selected;
	},
	
	build: function() {
		var $this = this;
		$(this.options.list).getElements( this.options.cur ).each( function( el ) {
			el.addEvent( 'click', function() {
				if( el.id != $this.get() ) $this.set( el.id );
			} );
		} );
	}
	
} );

var Contact = new Class( {

	Implements: Options,
	
	options: {
		src: '/?page=Widgets&plugins=Contact',
		open: false,
		iframe: {
			element: null,
			width: 500,
			height: 330,
			top_height: 20
		}
	},
	
	open: function() {
		if( this.options.open == false ) this.build();
		this.options.open = true;
	},
	
	build: function() {
		var form = new Element( 'div',  {
			styles: {
				'width': this.options.iframe.width,
				'height': this.options.iframe.height,
				'position': 'absolute',
				'top': 145,
				'left': ( ( window.getSize().x - 1000 ) / 2 + 310 ),
				'background-color': '#FFFFFF',
				'border': '1px #3871A5 solid',
				'overflow': 'hidden',
				'z-index': 1000
			}
		} );
		var html =	'<span style="float: left; margin-left: 10px;">' + _d( 'CONTACT US' ) + '</span>'+
								'<span style="float: right; margin-right: 3px;"><a href="javascript: Contact.close()">' +
								'<img src="/I/ico/cancel.gif" width="17" height="17" border="0" alt="' + _d( 'CLOSE' ) + '" title="' + _d( 'CLOSE' ) + '" />' +
								'</a></span>';
		var top = new Element( 'div', {
			styles: {
				'background-color': '#3871A5',
				'color': '#FFFFFF',
				'height': this.options.iframe.top_height,
				'cursor': 'move'
			},
			html: html
		} ).inject( form, 'top' );
		
		var iframe = new Element( 'iframe', {
			'src': this.options.src,
			'width': this.options.iframe.width,
			'height': this.options.iframe.height,
			'scrolling': 'none',
			'frameborder': 0
		} ).inject( form, 'bottom' );
		
		form.makeDraggable();
		this.options.iframe.element = form;
		form.inject( document.body, 'top' );
		
	},
	
	close: function() {
		if( this.options.open == true ) {
			this.options.iframe.element.destroy();
		}
		this.options.open = false;
	}
	
} );

var Help = new Class( {
	
	Implements: Options,
	
	initialize: function() {
	
		var $this = this;
		
		window.addEvent( 'domready', function() {
			$this.help = new Tips( '.help', {
				title: function( el ) {
					el.store( 'tip:title', _d( 'HELP' ) );
				},
				text: 'title',
				fixed: true,
				onShow: function( tip, hovered ) {
					tip.setStyle( 'display', 'block' );
				    var y = 0 - tip.getSize().y;
				    this.options.offset={x:0,y:y};
				}
			} );
		} );
	
	}
	
} );

Common = new Common;
