/*
 * anchor legend
 * 
 * F: filter
 * - requires dom element with id "filter_F(c|co|etc.)123", otherwise the filter will be ignored
 *   c: category
 *   co: country
 *   i: indicator
 *   s: stars
 *   st: state
 *   
 * L: list
 *   p: page TODO
 *   
 * H: hotel
 *   i: id
 *   t: tab
 *   
 * P: package
 *   i: id
 *   
 * R: roomtype
 *   i: id
 *   
 * PR: program
 *   g: group (grouped by indicator)
 *   i: id
 *   
 * A: anchors
 *   off: dont initialize anchor 
 * 
 */
_lib_load_libs_loaded['jQuery'] = true;

_lib_load_libs['jQuery-UI'] = [
	'/static/js/jquery-ui-1.8.1.custom/js/jquery-ui-1.8.1.custom.min.js',
	'/static/js/jquery-ui-1.8.1.custom/css/smoothness/jquery-ui-1.8.1.custom.css'
];

if ( typeof JSON == 'undefined' ) {
	jQuery( 'head:first' ).append( '<scr' + 'ipt src="/static/js/jquery.labs_json.js" type="text/javascript"></scr' + 'ipt>' );
}

function bw(){};

bw.settings = false;
bw.speed = 300;
bw.scroll = false;
bw.client_width = false;
bw.resolution = false;
bw.debug = false;

if( window.location.hostname.indexOf( '.rm.webdev' ) != -1 || window.location.hash.indexOf( 'Debug' ) != -1 ) {
	bw.debug = window.console && ( window.console.firebug || window.console.firebugVersion );
}

bw.loading = false;
bw.cookie = {};
bw.cookie_name = 'notices';
bw.anchor_watcher_paused = 0;
bw.anchor = '';
bw.anchor_old = '';
bw.anchors = {};
bw.anchors_old = {};
bw.onready_callbacks = [];
bw.resolution_timeout = false;
bw.keys_pressed = [];
bw.filter_menu_timer;

if ( bw.debug ) {
	console.warn( 'page loaded' );
	jQuery(function(){
		jQuery( 'body' ).addClass( 'debug' );
		jQuery( document.createElement( 'div' ) )
			.addClass('debug')
			.css({
				position: 'absolute',
				top: 5,
				left: '48%',
				color: 'red',
				fontSize: '15px',
				fontWeight: 'bold',
				padding: '10px',
				background: 'transparent',
				opacity: 0.75,
				'z-index': 99999
			})
			.text( 'debug' )
			.appendTo( 'body' );
	})
};

/*
 * removes all path information
 */
bw.url_validate = function ( url, layout_small ) {
	if ( bw.debug ) console.debug( 'bw.url_validate( ' + url + ' )' );
	if ( !url ) return false;
	
	if ( url.indexOf( '/' ) != -1 ) {
		var parts = url.split( '/' );
		
		/* break on other hostnames */
		if ( url.substring( 0, 4) == 'http' && parts[2] != window.location.hostname ) {
			return url;
		}
		
		url = parts[parts.length-1];
	}
	
	url += ( url.indexOf( '?' ) == -1 ? '?' : '&' ) + 'sys_layout=' + ( layout_small !== false ? 'small' : 'full' );
	
	if ( url.indexOf( 'hotel-list.php' ) != -1 ) {
		url += '&list_item_count=' + bw.list_item_count_get();
	}
	
	return '/ajax/' + url;
};

/*
 * parse a url and remove the query
 */
bw.redir = function( url ) {
	if ( bw.debug ) console.debug( 'bw.redir( ' + element + ' )' );
	if ( !url ) return false;
	
	var path = url.substring( 0, url.lastIndexOf( '/' ) + 1 ),
		anchor = url.substring( url.indexOf( '#' ) );
	
	window.location = path + anchor; 
}

/*
 */
bw.anchor_get_value = function ( category, name, anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchor_get_value( ' + category + ', ' + name + ', ' + anchors + ' )' );
	if ( anchors == undefined ) anchors = bw.anchors;

	if ( anchors[category] != undefined && anchors[category][name] != undefined ) {
		return anchors[category][name];
	}
	
	return false;
};

/*
 * set the given anchor - with some intelligence :)
 * if the given anchor alread exist, the existing value will be overwritten
 */
bw.anchor_set = function ( category, name, value, anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchor_set( ' + category + ', ' + name + ', ' + value + ', ' + anchors + ' )' );

	if ( !bw.anchors[category] ) {
		bw.anchors[category] = {};
	}
	// we dont want invalid hotel <> (P|PT|R) combinations
	else if ( category == 'H' && name == 'i' ) {
		bw.anchors = bw.anchor_remove_uniques( 'H' );
	}

	bw.anchors[category][name] = [ value.toString() ];
	bw.anchors_write();
};

/*
 * append the given anchor
 * if the anchor alread exist, the given value will be appended without removing the existing
 */
bw.anchor_append = function ( category, name, value ) {
	if ( bw.debug ) console.debug( 'bw.anchor_append( ' + category + ', ' + name + ', ' + value + ' )' );

	if ( bw.anchor_exist( category, name, value ) ) {
		bw.anchors = bw.anchor_remove( category, name, value );
	}
	
	if ( !bw.anchors[category] ) {
		bw.anchors[category] = {};
	}
	
	if ( !bw.anchors[category][name] ) {
		bw.anchors[category][name] = [];
	}
	
	bw.anchors[category][name].push( value );
}	

/*
 * remove or append the given anchor
 */
bw.anchor_toggle = function ( category, name, value ) {
	if ( bw.debug ) console.debug( 'bw.anchor_toggle( ' + category + ', ' + name + ', ' + value + ' )' );
	
	if ( bw.anchor_exist( category, name, value ) ) {
		bw.anchors = bw.anchor_remove( category, name, value )
	}
	else {
		bw.anchor_append( category, name, value )
	}
}	

/*
 * remove the given anchor
 */
bw.anchor_remove = function ( category, name, value, anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchor_remove( ' + category + ', ' + name + ', ' + value + ', ' + anchors + ' )' );
	if ( !category ) return false;
	if ( !anchors ) anchors = bw.anchors;
	
	var result = {};
	
	// check if the anchor exists
	if ( bw.anchor_exist( category, name, value, anchors ) === false ) {
		return anchors;
	}
	
	jQuery.each( anchors, function( c ){
		// if no name is set, remove the complete category
		if( category == c && !name ) return;
		
		result[c] = {};
		
		jQuery.each( anchors[c], function( n ){
			// remove a complete name with all its values out of a category
			if( category == c && name == n && !value ) return;

			result[c][n] = [];
		
			jQuery.each( anchors[c][n], function( i, v ){
				// remove a single value out of a name
				if ( category == c && name == n && value == v ) return;
				
				result[c][n].push( v )
			});
			
			if ( result[c][n].length == 0 ) {
				delete result[c][n];
			}
		});
	});
	
	anchors = result;
	
	return result;
};

/*
 * some categories cant be combined, otherwise we dont know which we have to load
 */
bw.anchor_remove_uniques = function ( category, anchors  ) {
	if ( bw.debug ) console.debug( 'bw.anchor_remove_uniques( ' + category + ', ' + anchors + ' )' );
	if ( !anchors ) anchors = bw.anchors;
	if ( anchors.length == 0 ) return;

	switch( category ) {
		case 'P':
			anchors = bw.anchor_remove( 'PR', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'R', undefined, undefined, anchors );
		break;
		case 'PR':
			anchors = bw.anchor_remove( 'P', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'R', undefined, undefined, anchors );
		break;
		case 'R':
			anchors = bw.anchor_remove( 'P', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'PR', undefined, undefined, anchors );
		break;
		case 'H':
			anchors = bw.anchor_remove( 'P', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'PR', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'R', undefined, undefined, anchors );
		break;
		case 'F':
			anchors = bw.anchor_remove( 'H', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'P', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'PR', undefined, undefined, anchors );
			anchors = bw.anchor_remove( 'R', undefined, undefined, anchors );
		break;
	}

	return anchors;
};

/*
 * read the current anchor
 */
bw.anchors_get = function () {
	if ( bw.debug ) console.debug( 'bw.anchors_get()' );
	
	bw.anchors = bw.anchors_decode();
	
	return bw.anchors;
};

/*
 * set an array of anchors
 */
bw.anchors_set = function ( anchors, unique ) {
	if ( bw.debug ) console.debug( 'bw.anchors_set( ' + anchors + ' )' );
	
	if (unique) {
		bw.anchors = bw.anchor_remove_uniques(unique);
	}
	
	jQuery.each( anchors, function( i, anchor ){
		if ( anchor.category == undefined ) return;

		if ( bw.anchors[anchor.category] == undefined ) {
			bw.anchors[anchor.category] = {};
		}

		bw.anchors[anchor.category][anchor.name] = new Array(  anchor.value.toString() );
	});
	
	bw.anchors_write();
};

/*
 * when the anchor has changed, re-init them
 */
bw.anchors_reinit = function(){
	if ( !bw.inited ) return;
	if ( window.location.hash == bw.anchor ) return;
	if ( bw.debug ) {
		console.debug( 'bw.anchors_reinit()' );
		console.info( 'anchor has changed' + ( bw.anchor_watcher_paused != 0 ? ', but watcher is paused' : ', running activities' ) );
	}

	bw.anchor_old = bw.anchor;
	bw.anchor = window.location.hash;
	
	bw.anchors_old = bw.anchors_decode( bw.anchor_old );
	bw.anchors = bw.anchors_decode( bw.anchor );

	if ( bw.debug ) {
		console.group( 'anchors' );
		console.log( 'old anchor: %s', bw.anchor_old );
		console.dir( bw.anchors_old );
		console.log( 'new anchor: %s', bw.anchor );
		console.dir( bw.anchors );
		console.groupEnd();
	}

	// dont initialize the anchors, just ignore them
	if ( bw.anchor.indexOf( 'Aoff' ) != -1 ) {
		return;
	}

	if ( bw.anchor_watcher_paused == 0 ) {
		bw.anchors_init();		
	}
	else {
		bw.anchor_watcher_paused--;
	}
};

/*
 * check every 500 ms if the anchor has changed
 */
bw.anchor_watcher = function () {
	if ( bw.debug ) console.debug( 'bw.anchor_watcher()' );

	// the onhashchange event of some browser is to buggy, so we check it manually
	bw.anchor_watcher_timer = setInterval(function() {
		var anchor = window.location.hash;
		
		if (anchor.length > 0 && anchor.indexOf( 'Aoff' ) == -1 ) {
			bw.anchors_reinit();
		}
	}, 500 );
};

/*
 * check every 500 ms if the anchor has changed
 */
bw.anchor_watcher_pause = function ( num ) {
	if ( bw.debug ) console.debug( 'bw.anchor_watcher_pause( ' + num + ' )' );
	
	bw.anchor_watcher_paused += ( num || 1 );
};

/*
 * reset pause num
 */
bw.anchor_watcher_reset = function () {
	if ( bw.debug ) console.debug( 'bw.anchor_watcher_reset()' );
	
	bw.anchor_watcher_paused = 0;
};

/* 
 * check if a anchor exists
 */
bw.anchor_exist = function ( category, name, value, anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchor_exist( ' + category + ', ' + name + ', ' + value + ', ' + anchors + ' )' );
	if ( !anchors ) anchors = bw.anchors;
	
	var exist = false;
	
	if ( category && name && value != undefined ) {
		if ( anchors[category] != null && anchors[category][name] != null ) {
			if (jQuery.inArray(value, anchors[category][name]) != -1) {
				exist = true;
			}
		}
	}
	else if ( category && name ) {
		if ( anchors[category] != null && anchors[category][name] != null && anchors[category][name].length > 0 ) {
			exist = true;
		}
	}
	else if ( category ) {
		if ( anchors && anchors[category] ) {
			exist = true;
		}
	}

	return exist;
};

/* 
 * generate a valid url from the given anchor and load it
 */
bw.anchor_select = function ( category, name, value ) {
	if ( bw.debug ) console.debug( 'bw.anchor_select( ' + category + ', ' + name + ', ' + value + ' )' );
	if ( name != 'i' ) return false;
	
	if ( category + name == 'Lp' ) {
		jQuery( 'div#list_navigation_pagina a.selected' ).removeClass( 'selected' );
	}
	
	var anchor = category + name + value;
	
	jQuery( 'a[rev=' + anchor + ']' ).addClass( 'selected' )
	
	if ( !bw.anchors[category] || !bw.anchors[category][name] ) {
		return false;
	}
		
	if( category == 'H' ) {
		var tab = bw.anchor_get_value( 'H', 't' )[0],
			tab_old = bw.anchor_get_value( 'H', 't', bw.anchors_old )[0],
			hotel_old = bw.anchor_get_value( 'H', 'i', bw.anchors_old )[0];

		if ( !hotel_old || hotel_old != value || tab_old != tab ) {
			switch( tab ) {
				case "2":
					var url = 'hotel-detail-gallery-list.php?hotel=' + value;
				break;
				case "3":
					var url = 'package-list.php?type=1&c[ids_hotels][]=' + value;
				break;
				case "4":
					var url = 'hotel-room-list.php?hotel=' + value;
				break;
				/*
				case 5:
					var url = 'hotel-program-list.php?hotel=' + value;
				break;
				*/
				case "6":
					var url = 'request.php?page=2.page1&hotel_id=' + value;

					if(bw.anchor_exist( 'P', 'i' )) {
						url += '&remember[hpa]=' + bw.anchor_get_value( 'P', 'i' );
					}
					
					if(bw.anchor_exist( 'R', 'i' )) {
						url += '&remember[hpa]=' + bw.anchor_get_value( 'R', 'i' );
					}
				break;
				/*
				case 7:
					var url = 'search.php?hotel=' + value;
				break;
				*/
				default:
					var url = 'hotel-detail.php?id=' + value;
				break;
			}
		}

		bw.list_detail_show( url, value );
	}
};

/*
 * write the given anchor into the uri
 */
bw.anchors_write = function ( anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchors_write( ' + anchors + ' )' );
	
	if ( anchors == undefined ) {
		anchors = bw.anchors;
	}
	
	if ( bw.isEmptyObject(anchors) && bw.anchor == '' ) {
		return false;
	}
	
	bw.nodelay(function(){
		var anchor = '';
		
		if ( !bw.isEmptyObject(anchors) ) {
			anchor = bw.anchors_encode(anchors);
		}
		
		window.location.hash = anchor;
	}.bind(anchors));
};

/* duration: 1ms
 * load the current anchor
 */
bw.anchors_init = function ( fn ) {
	if ( bw.debug ) console.debug( 'bw.anchors_init()' );
	
	jQuery.each( bw.anchors, function( category, index ){
		if ( jQuery( bw.anchors[category] ).size() > 0 ) {
			jQuery.each( bw.anchors[category], function( name ){
				if ( bw.anchors[category][name].length > 0 ) {
					for( var i = 0; i < bw.anchors[category][name].length; i++ ) {
						bw.anchor_select( category, name, bw.anchors[category][name][i] );
					}
				}
			});
		}
	});
	
	if ( typeof fn == 'function'  ) {
		fn();
	}
};

/*
 * convert an anchor array into a string
 */
bw.anchors_encode = function ( anchors ) {
	if ( bw.debug ) console.debug( 'bw.anchors_encode( ' + anchors + ' )' );
	if ( anchors == undefined ) return;

	var string = '';

	jQuery.each( anchors, function( category ){
		if ( jQuery( anchors[category] ).size() > 0 ) {
			string += category;
			jQuery.each( anchors[category], function( name ){
				if ( typeof anchors[category][name] == 'object' ) {
					string += name + anchors[category][name].join( ',' );
				}
				else {
					string += name + anchors[category][name];
				}
			});
			
			if ( string.charAt( string.length - 1 ) == category ) {
				string = string.substring( 0, string.length - 1 );
			}
		}
	});

	return string;
};

/*
 * convert an anchor string into an array
 */
bw.anchors_decode = function ( anchor ) {
	if ( bw.debug ) console.debug( 'bw.anchors_decode( ' +typeof anchor + ' )' );

	var category = '',
		category_current = '',
		name = '',
		name_current = '',
		value = '',
		result = {};
	
	if ( typeof anchor == 'undefined' ) {
		anchor = window.location.hash.substring( 0 );
		
		if ( anchor.indexOf( 'Aoff' ) != -1 ) {
			anchor = '';
		}
	}

	if ( anchor.length == 0 ) return result;
	
	var length = anchor.length,
		character = '',
		code = '';
		
	for( var i = 1; i < length; i++ ) {
		char = anchor.charAt( i );
		code = anchor.charCodeAt( i );

		// category: A - Z or , (comma)
		if ( ( code >= 65 && code <= 90 ) || code == 44 ) {
			if ( value.length > 0 ) {
				if ( typeof result[category_current][name_current] == 'undefined' ) {
					result[category_current][name_current] = new Array( value );
				}
				else {
					result[category_current][name_current].push( value );
				}
			}
			
			if ( code != 44 ) {
				name = '';
				category += char;
			}

			value = '';
		}
		// name: a - z
		else if ( code >= 97 && code <= 122 ) {
			if ( category.length > 0 ) {
				category_current = category;
				category = '';
			}
			if ( result[category_current] == undefined ) {
				result[category_current] = {};
			}
			if ( value.length > 0 ) {
				if ( result[category_current][name_current] == undefined ) {
					result[category_current][name_current] = new Array( value );
				}
				else {
					result[category_current][name_current].push( value );
				}
			}
			value = '';
			name += char;
			name_current = name;
		}
		// value: 0 - 9
		else if ( code >= 48 && code <= 57 ) {
			name = '';
			if ( result[category_current] && result[category_current][name_current] == null ) {
				result[category_current][name_current] = new Array();
			}
			value += char;
		}
		// ignore other characters
	}
	
	if ( category_current && name_current && value ) {
		result[category_current][name_current].push( value );
	}
	
	if ( bw.debug ) {
		console.group( 'bw.anchors_decode()' );
		console.dir( result );
		console.groupEnd();
	}

	return result;
};

/* execute some very slow operations in an other scope */
bw.nodelay = function( fn ){
	if ( bw.debug ) console.debug( 'bw.nodelay( ' + typeof fn + ' )' );
	
	window.setTimeout(function(){
		fn();
	}, 1 );
};

bw.class_loading_add = function( selector, delay ) {
	if ( bw.debug ) console.debug( 'bw.class_loading_add( ' + selector + ' )' );
	if ( !selector ) return;
	
	if ( delay ) {
		window.setTimeout(function(){
			jQuery( selector ).addClass( 'bw_loading' );
		}, delay );
	}
	else {
		jQuery( selector ).addClass( 'bw_loading' );
	}
};

bw.class_loading_remove = function(){
	if (bw.debug) console.debug('bw.class_loading_remove()');
	
	// acutally we can remove all loading classes at once
	jQuery('.bw_loading').removeClass('bw_loading')
}

/*
 * load the given url and call a callback function
 */
bw.content_load = function ( options, fn ) {
	if ( bw.debug ) console.debug( 'bw.content_load( ' + options + ', ' + typeof fn + ' )' );
	if ( !options || !options.uri ) return false;

	var data,
		defaults = {
			type: 'GET',
			dataType: 'html',
			cache: false,
			async: true
		}
	
	settings = jQuery.extend( true, defaults, options );
	
	if ( options.uri.indexOf( '?' ) != -1 ) {
		url = options.uri.substring( 0, options.uri.indexOf( '?') )
		data = options.uri.substring( options.uri.indexOf( '?') + 1 );
	}

	bw.loading = true;
	
	jQuery.ajax({
		type: settings.type || 'GET',
		dataType: settings.dataType || 'html',
		cache: settings.cache || false,
		async: settings.async || true,
		url: url,
		data: data,
		complete: function(){
			bw.loading = false;
			bw.class_loading_remove();
		},
		success: function( response ){
			if ( typeof fn == 'function' ) {
				if( settings.dataType == 'html' ) {
					var scripts = [];
					response = jQuery( response );
				
					jQuery.each( response, function(k,v){
						if( v.tagName && v.tagName.toLowerCase() == 'script' && v.getAttribute( 'rev' ) != 'ignore' ) {
							scripts.push( v );
							delete response[k];
						}
					});
					jQuery( 'head' ).append( scripts );
				}
				
				fn( response );
			}
		},
		error: function( XMLHttpRequest, textStatus, errorThrown ){
			if ( bw.debug ) console.warn( 'error!', XMLHttpRequest, textStatus, errorThrown );
		}
	});
};

/*
 * slide toggle replacement
 */
bw.content_toggle = function( marker ) {
	if ( bw.debug ) console.debug( 'bw.content_toggle( ' + marker + ' )' );
	
	var element = jQuery( marker + '_content' ),
		opener = jQuery( marker + '_more' );
	
	if ( element.hasClass( 'active' ) ) {
		opener.removeClass( 'active' );
		element
			.removeClass( 'active' )
			.slideUp();
	}
	else {
		opener.addClass( 'active' );
		element
			.addClass( 'active' )
			.slideDown();
	}
};

/*
 * scroll to an element and call callback function
 */
bw.scroll_to = function( selector, fn ) {
	if ( bw.debug ) console.debug( 'bw.scroll_to( ' + selector + ' ,' + typeof fn + ' )' );
	if ( selector == undefined ) return false;
	
	window.setTimeout(function(){
		if ( jQuery( selector ).length > 0 ) {
			jQuery( 'html,body' ).animate({ scrollTop: jQuery( selector ).offset().top }, bw.speed, null, function(){
				if ( typeof fn == 'function' ) {
					fn();
					fn = undefined;
				}
			});
		}
	}, 550 );
};

/*
 * scroll to the element, which matches to the current anchor
 */
bw.scroll_to_current = function(){
	if ( bw.debug ) console.debug( 'bw.scroll_to_current()' );
	
	var selector, remove;
	
	if ( typeof bw.anchors['PR'] != 'undefined' ) {
		selector = '#program_' + bw.anchors['PR']['i'];
		remove = false;
	}
	else if ( typeof bw.anchors['P'] != 'undefined' ) {
		selector = '#package_' + bw.anchors['P']['i'];
	}
	else if ( typeof bw.anchors['R'] != 'undefined' ) {
		selector = '#roomtype_' + bw.anchors['R']['i'];
	}

	bw.scroll_to( selector, function(){
		bw.content_toggle( selector );
	});
};

bw.filter_init = function( options ){
	if ( bw.debug ) console.debug( 'bw.filter_init( ' + options + ')' );

	var filters = jQuery( '#bw_filter_criterias' ).children();
	
	bw.settings.filter = options || {};

	bw.filters_select();
	
	filters.each(function(){
		var filter = this;
		
		jQuery( '> div:eq(0)', filter )
			.bind( 'mouseenter', function(){
				bw.filter_menu_timer = window.setTimeout(function(){
					var filter_content = jQuery( filter ).find( '> div:eq(1)' );
					
					filters
						.find( 'div.bw_filter_categorie_content:visible' )
						.slideUp();
					
					filter_content
						.bind( 'mouseleave', function(){
							jQuery( this ).slideUp();
						})
						.slideDown();
				}, 150 );
			})
			.bind( 'mouseleave', function(){
				window.clearTimeout( bw.filter_menu_timer );
			});
	});
}

/*
 * apply all filters, close detail view and show hotel list
 */
bw.filter_apply = function ( hide_detail_view ) {
	if ( bw.debug ) console.debug( 'bw.filter_apply()' );

	if ( hide_detail_view && bw.anchor_exist( 'H' ) ) {
		bw.anchor_remove( 'H' );
	}

	var bw_list = jQuery( '#bw_list' ),
		bw_detail = jQuery( '#bw_detail' ),
		filter = bw.filters_get(),
		page = 0;
	
	bw.class_loading_add( bw_list );

	var url = filter.join( '&' );

	if ( url.length == 0 ) {
		url = '/hotel-list.php?';
	}
	
	if ( !bw.anchor_exist( 'F' ) || bw.isEmptyObject( bw.anchors_old ) ) {
		url += '&c[ids_indicators_logic_and]=1&c[ids_countries_states_logic_or]=1';
	}
	
	if ( bw.anchor_exist( 'L', 'p' ) ) {
		url += '&page_force=0&page=' + parseInt( bw.anchor_get_value( 'L', 'p' ), 10 );
	}

	bw.anchors_write();

	// uncollapse hotel list and hide detail view, if visible
	if( hide_detail_view === undefined && bw_list.hasClass( 'bw_list_collapsed' ) ) {
		bw_detail
			.fadeOut( bw.speed )
			.empty();
			
		bw.list_uncollapse( bw_list );
	}

	// dont use bw.speed on first loading, there is nothing that we can hide
	bw_list.fadeOut( ( bw_list.children().size() == 0 ? 0 : bw.speed ), function(){
		bw.content_load( { uri: bw.url_validate( url, ( jQuery( '#list_container' )[0] == undefined ) ) }, function( response ){
			var content = response.find( '#list_pages' );

			if ( content[0] ) {
				bw_list
					.html( content.html() )
					.append( response.find( '#list_navigation' ) )
					.show()
					
				bw.list_init( bw_list );
			}
			else {
				bw_list
					.width( '100%' )
					.html( response.find( '#bw_error' ).html() )
					.show();
			}
		});
	});
};

/*
 * open filter view
 */
bw.filter_show = function () {
	if ( bw.debug ) console.debug( 'bw.filter_show()' );

	jQuery( '#bw_filter_criterias' )
		.removeClass( 'bw_filter_collapsed' )
		.css({
			'overflow': 'visible',
			'height': 'auto'
		})
		.slideDown();
};

/*
 * close filter view
 */
bw.filter_hide = function ( fn ) {
	if ( bw.debug ) console.debug( 'bw.filter_hide()' );

	var bw_list_criterias = jQuery( '#bw_filter_criterias' );
	
	if ( !bw_list_criterias.hasClass( 'bw_filter_collapsed' ) ) {
		bw_list_criterias
			.addClass( 'bw_filter_collapsed' )
			.css( 'overflow', 'hidden' )
			.animate({ height: 15 }, bw.speed, null, function(){
				if ( typeof fn != 'function' ) {
					fn = function(){};
				}
				
				jQuery( this ).hide();
			});
	}
};

/*
 * get all selected filters out of the dom
 * @return array
 */
bw.filters_get = function () {
	if ( bw.debug ) console.debug( 'bw.filters_get()' );

	var filters = jQuery( '#bw_filter_criterias' ).find( 'a.selected' ),
		params = [],
		url;
	
	if ( filters.length == 0 ) {
		return params;
	}
	
	filters.each(function( i ){
		url = jQuery( this, i ).attr( 'href' );

		if ( params.length > 0 ) {
			url = url.substring( url.indexOf( '?' ) + 1 );
		}

		params.push( url );
	});

	if ( params.length > 0 ) {
		params.push( 'c[ids_indicators_logic_and]=1' );
		params.push( 'c[ids_countries_states_logic_or]=1' );
	}
	
	return params;
};

/*
 * mark the dom element which controls the filter as selected or not 
 */
bw.filter_select = function ( element ) {
	if ( bw.debug ) console.debug( 'bw.filter_select( ' + element + ' )' );
	
	jQuery( element ).addClass( 'selected' );
};

/*
 * mark filter as selected by anchor array 
 */
bw.filters_select = function ( anchors, fn ) {
	if ( bw.debug ) console.debug( 'bw.filters_select( ' + anchors + ', ' + typeof fn + ' )' );
	
	var filter = jQuery( '#bw_filter_criterias' );
	
	if ( !filter[0] ) return false;
	if ( !anchors ) anchors = bw.anchors;
	
	jQuery.each( anchors, function( category ){
		if ( jQuery( anchors[category] ).size() > 0 ) {
			jQuery.each( anchors[category], function( name ){
				jQuery.each( anchors[category][name], function( i, value ){
					bw.filter_select( '#filter_' + category + name + value );
				});
			});
		};
	});
	
	if ( fn ) {
		fn();
	}
};

/*
 * add a new list
 */
bw.list_init = function( container ) {
	if ( bw.debug ) console.debug( 'bw.list_init( ' + container + ' )' );

	bw.settings.list = {
		container: container,
		navigation: {
			container: container.find( '#list_navigation' )
		}
	}
	
	bw.settings.list.navigation.next = bw.settings.list.navigation.container.find( 'a:eq(0)' ).click(function(){
		if ( !bw.loading ) {
			bw.loading = true;
			bw.anchor_watcher_pause();
			bw.list_page_load( 'next' );
		}
		return false;
	});
	
	bw.settings.list.navigation.prev = bw.settings.list.navigation.container.find( 'a:eq(1)' ).click(function(){
		if ( !bw.loading ) {
			bw.loading = true;
			bw.anchor_watcher_pause();
			bw.list_page_load( 'prev' );
		}
		return false;
	});
	
	bw.settings.list.navigation.links = bw.settings.list.navigation.container.find( 'a:gt(1)' ).click(function(){
		if ( !bw.loading ) {
			bw.loading = true;
			bw.anchor_watcher_pause();
			bw.list_page_load( parseInt( jQuery( this ).addClass( 'visited' ).text(), 10 ) - 1 );
		}
		return false;
	});
	
	bw.settings.list.navigation.link_count = bw.settings.list.navigation.links.size()
	var url = bw.settings.list.navigation.links.eq( 0 ).attr( 'href' );
	bw.settings.list.navigation.url = url.substring( 0, url.indexOf( '=' ) + 1 );
	
	if ( bw.anchor_exist( 'H', 'i' ) ) {
		bw.settings.list.container
			.find( '.bw_box' )
			.addClass( 'bw_box_green' )
			.filter( '[rev="Hi' + bw.anchor_get_value( 'H', 'i' )[0] + '"]' )
			.removeClass( 'bw_box_green' );
	}
};

bw.list_item_count_get = function(){
	return bw.client_width < 1050 ? 3 : 6;
}

/*
 * load new content for listings (a.k.a new page)
 * first content is loaded by bw.filter_apply()
 */
bw.list_page_load = function ( page ) {
	if ( bw.debug ) console.debug( 'bw.list_page_load( ' + page + ' )' );
	
	if ( typeof page == 'undefined' ) {
		bw.loading = false;
		return;
	};

	var page_current = parseInt( bw.anchor_get_value( 'L', 'p' ) || 0, 10 ),
		list_page_current = jQuery( '#list_page' + page_current ),
		list_page_width = list_page_current.width();

	if( page == 'next' ) {
		page = page_current + 1;
	}
	else if ( page == 'prev' ) {
		page = page_current - 1;
	}
	
	if ( page < 0 || page >= bw.settings.list.navigation.link_count ) {
		bw.loading = false;
		return false;
	}
	
	bw.settings.list.navigation.links
		.filter( '.selected' )
		.removeClass( 'selected' )
		.end()
		.eq( page )
		.addClass( 'selected visited' )

	bw.class_loading_add( bw.settings.list.container, bw.speed );
	
	var list_page_new = jQuery( '#list_page' + page );

	if ( !list_page_new[0] ) {
		list_page_new = jQuery( document.createElement( 'div' ) )
			.attr( 'id', 'list_page' + page )
			.addClass( 'list_page hidden' )
			.load( bw.url_validate( bw.settings.list.navigation.url.toString() + page.toString() ) + ' #list_page' + page );	

		if ( page < page_current ) {
			list_page_new.insertBefore( list_page_current );
		}
		else {
			list_page_new.insertAfter( list_page_current );
		}
	}
	
	list_page_current
		.width( '100%' )
		.animate({ marginLeft: ( ( list_page_current.width() ) * ( page < page_current ? 1 : -1 ) ) }, {
			duration: ( jQuery.browser.safari ? bw.speed : bw.speed * 3 ),
			easing: 'easeOutQuint',
			complete: function() {
				bw.class_loading_remove();
				
				list_page_current.addClass( 'hidden' );

				list_page_new
					.css({
						margin: 0
					})
					.removeClass( 'hidden' );

				bw.anchor_watcher_reset();
				bw.loading = false;
			}
		});
	
	bw.anchor_watcher_pause();
	bw.anchor_set( 'L', 'p', page );
};

/*
 * hide filters and load the hotel detail view
 */
bw.list_detail_show = function ( url, hotel ) {
	if ( bw.debug ) console.debug( 'bw.list_detail_show( ' + url + ' , ' + hotel + ' )' );
	if ( !url ) return;
	
	var bw_list = jQuery( '#bw_list' );
	var bw_detail = jQuery( '#bw_detail' );
	
	bw_list
		.find( '.bw_box' )
		.addClass( 'bw_box_green' )
		.filter( '[rev="Hi' + hotel + '"]' )
		.removeClass( 'bw_box_green' );
	
	bw.class_loading_add( bw_detail );
	bw.class_loading_add( '#detail_contents' );
		
	// collapse hotel list und show hotel detail view
	if( bw_list[0] && !bw_list.hasClass( 'bw_list_collapsed' ) ) {
		bw.content_load( { uri: bw.url_validate( url, false ) }, function( response ){
			bw_detail
				.empty()
				.html( response.find( '#bw_detail_content' ) );
		});
	
		bw.list_collapse( bw_list, function(){
			bw_detail
				.removeClass( 'hidden' )
				.show()
			bw.scroll_to_current();
		});
	}
	
	// load new detail view content (same hotel)
	else if ( !bw_list[0] || bw.anchor_get_value( 'H', 'i' )[0] == bw.anchor_get_value( 'H', 'i', bw.anchors_old )[0] ) {
		jQuery( '#cst-hotel-detail-menu li' )
			.removeClass( 'active' )
			.filter( '#hotel-detail-tab' + bw.anchor_get_value( 'H', 't' )[0] + '-container' )
			.addClass( 'active' );
			
		jQuery( '#detail_content' ).hide();
			
		bw.content_load( { uri: bw.url_validate( url, true ) }, function( response ){
			jQuery( '#detail_content' )
				.empty()
				.html( response )
				.show();

			if ( bw.scroll ) {
				bw.scroll_to_current();
			}
		});
	}
	
	// hide current detail view and load new one (other hotel)
	else {
		bw_detail
			.find( '#bw_detail_content:first' )
			.fadeOut( bw.speed, function(){
				bw_detail.empty();
				
				bw.content_load( { uri: bw.url_validate( url, false ) }, function( response ){
					bw_detail.html( response.find( '#bw_detail_content' ) );
					
					if ( bw.scroll ) {
						bw.scroll_to_current();
					}
				});
			});
	}
};

/*
 * hide filters and load the hotel detail view
 */
bw.list_detail_hide = function() {
	if ( bw.debug ) console.debug( 'bw.list_detail_hide()' );

	jQuery( '#bw_detail' ).addClass( 'hidden' );
};

/*
 * colapse hotel list into teaser
 * 
 */
bw.list_collapse = function( list, fn ) {
	if ( bw.debug ) console.debug( 'bw.list_collapse( ' + list + ', ' + typeof fn + ' )' );
	if ( !list ) return false;
	if ( !fn ) fn = function(){};

	var list_width = ( bw.list_item_count_get() == 6 ? 462 : 228 )

	list
		.addClass( 'bw_list_collapsing' )
		.children()
		.width( 'auto' )
		.end()
		.animate({ width: list_width }, bw.speed, null, function(){
			list
				.removeClass( 'bw_list_collapsing' )
				.addClass( 'bw_list_collapsed' )
				.width( list_width )
				.find( 'div#list_pages' );
			
			list.css( 'overflow', 'hidden' );

			jQuery( '#bw_filter_back_holder' ).removeClass( 'hidden' );
			
			fn();
		});
};

bw.list_collapse_refresh = function( list ) {
	if ( bw.debug ) console.debug( 'bw.bw.list_collapse_refresh( ' + list + ' )' );
	if ( !list ) return false;

	list.width( bw.list_item_count_get() == 6 ? 462 : 228 );
};

/*
 * colapse hotel list into teaser
 * 
 */
bw.list_uncollapse = function( list, fn ) {
	if ( bw.debug ) console.debug( 'bw.list_uncollapse( ' + list + ', ' + typeof fn + ' )' );
	
	bw.list_detail_hide();
	bw.anchors_write( bw.anchor_remove_uniques( 'F', bw.anchors ) );
	
	jQuery( '#bw_filter_back_holder' ).addClass( 'hidden' );
	
	jQuery( list || '#bw_list' )
		.children()
		.removeAttr( 'style' )
		.children()
		.addClass( 'bw_box_green' )
		.end()
		.end()
		.animate({ width: '100%' }, bw.speed, undefined, function(){
			jQuery( this ).removeClass( 'bw_list_collapsing' );
		})
		.addClass( 'bw_list_collapsing' )
		.removeClass( 'bw_list_collapsed' );
		
	if ( fn ) fn();
};

/*
 * submit a form
 * 
 */
bw.form_submit = function ( form, options, fn ) {
	if ( bw.debug ) console.debug( 'bw.form_submit( ' + form + ', ' + options + ', ' + typeof fn + ' )' );
	if ( !form ) return false;
	
	var defaults = { ajax: true, validate: true },
		settings = jQuery.extend( true, defaults, options );
	
	bw.class_loading_add( '.bw_content_cst, #detail_contents' );

	if ( !settings.ajax ) {
		form
			.removeAttr( 'onsubmit' )
			.submit();
		return;
	}

	var params = bw.form_data_get( form );

	jQuery.ajax({
		type: 'POST',
		dataType: 'html',
		url: settings.validate ? bw.url_validate( form.attr( 'action' ), settings.layout ) : form.attr( 'action' ),
		data: params,
		async: false,
		cache: false,
		success: function( response ){
			if ( fn ) fn( response );
		},
		error: function( XMLHttpRequest, textStatus, errorThrown ){
			if ( bw.debug ) console.warn( 'error!', XMLHttpRequest, textStatus, errorThrown );
		}
	});
};

bw.form_validate = function( form ) {
	if ( bw.debug ) console.debug( 'bw.form_validate(' + form + ')' );

	jQuery( form )
		.find( "input:checked, input[type='text'], input[type='hidden'], input[type='password'], input[type='submit'], select, textarea" )
		.each(function() {
			var input = jQuery( this );

			if ( input.attr( 'placeholder' ) != '' && input.val() == input.attr( 'placeholder' ) ) {
				input.val( '' );
			}
		});
};

bw.form_data_get = function( form ) {
	if ( bw.debug ) console.debug( 'bw.form_data_get(' + form + ')' );

	var params = {};
	
	jQuery( form )
		.find( "input:checked, input[type='text'], input[type='hidden'], input[type='password'], input[type='submit'], select, textarea" )
		.each(function() {
			var input = jQuery( this );

			if ( input.attr( 'placeholder' ) != '' && input.val() == input.attr( 'placeholder' ) ) {
				input.val( '' );
			}
			
			params[this.name || this.parentNode.name] = this.value;
		});
		
	return params;
};

bw.form_data_get_elements = function( form ) {
	if ( bw.debug ) console.debug( 'bw.form_data_get_elements(' + form + ')' );

	return jQuery( form )
		.find( "input:checked, input[type='text'], input[type='password'], input[type='submit'], select, textarea" )
		.each(function() {
			var input = jQuery( this );

			if ( input.val() == input.attr( 'placeholder' ) ) {
				input.val( '' );
			}
		});
};

bw.search_init = function() {
	if ( bw.debug ) console.debug( 'bw.search_init()' );
	
	jQuery( 'input#bw_search_input' )
		.autocomplete( '/search/', {
			extraParams: {
				'search_limit_modules': 57,
				'search_format': 'json',
				'search_options[cst_mask]': 16
			},
			minChars: 3,
			max: 50,
			width: 290,
			delay: 150,
			multiple: false,
			matchContains: true,
			autoFill: false,
			scroll: true,
			scrollHeight: 250,
			resultsClass: 'bw_search_results',
			parse: function(data) {
				var result = [];
				jQuery.each( bw.json_decode( data ), function( i, r ) {
					result[result.length] = {
						value: r.id,
						result: r.title,
						data: r
					};
				})
				return result;
			},
			formatItem: function(item, i, max) { return '<a href="/de/urlaub/#Hi' + item.id + '">' + item.title + '</a>'; },
			formatMatch: function(item, i, max) { return item.title; },
			formatResult: function(item) { return item.title; }
		})
		.result(function(event, item) {
			window.location.href = '/de/urlaub/#Hi' + item.id;
			jQuery( this ).val( item.title );
			
			return false;	
		});
};

/*
 * check every 100ms the resolution width
 */
bw.resolution_init = function ( fn ) {
	if ( bw.debug ) console.debug( 'bw.resolution_init( ' + typeof fn + ' )' );

	bw.resolution_watcher( 'ready', fn  )
};

/*
 * check every 250ms the resolution width
 */
bw.resolution_watcher = function ( classname, fn ) {
	if ( bw.debug ) console.debug( 'bw.resolution_watcher( ' + classname + ', ' + typeof fn + ' )' );
	
	window.setInterval(function(){
		var client_width = jQuery( window ).width();

		if ( !bw.client_width || bw.client_width != client_width ) {
			bw.resolution_set( client_width, classname, fn );
			// delete fn doesnt work..
			fn = undefined;
		}
	}, 250 );
};

/*
 * check the current resolution and add/remove some classes to body
 */
bw.resolution_set = function ( client_width, classname, fn ) {
	if ( bw.debug ) console.debug( 'bw.resolution_set( ' + client_width + ', ' + classname + ', ' + typeof fn + ' )' );
	if ( !client_width ) client_width = jQuery( window ).width();
	if ( !classname ) classname = '';
	else classname += ' ';

	var body = jQuery( 'body' ),
		list_item_count = bw.list_item_count_get(),
		page_num = 0;

	/* this way it's a little bit faster :) */
	classname += body[0].className
		.replace(/(ready|res_width_915|res_width_1050|res_width_1200|res_width_1350|res_width_1500|res_width_1650)/g, '')
		.replace (/^\s+/, '')
		.replace (/\s+$/, '');
	
	if ( bw.debug ) {
		console.info( 'screen: ' + screen.width + 'x' + screen.height ); 
		console.info( 'browser: ' + client_width + 'x' + jQuery( window ).height() );
	}

	if ( client_width >= 915 ) {
		classname += ' res_width_915';
	}
	if ( client_width >= 1050 ) {
		classname += ' res_width_1050';
	}
	if ( client_width >= 1200 ) {
		classname += ' res_width_1200';
	}
	if ( client_width >= 1350 ) {
		classname += ' res_width_1350';
	}
	if ( client_width >= 1500 ) {
		classname += ' res_width_1500';
	}
	if ( client_width >= 1680 ) {
		classname += ' res_width_1650';
	}
	
	if ( bw.anchor_exist( 'L', 'p' ) ) {
		page_num = parseInt( bw.anchor_get_value( 'L', 'p' ), 10 );
	}
	
	if( client_width < 1050 ) {
		page_num = page_num > 0 ? page_num * 2 : 0;
	}
	else {
		page_num = page_num > 0 ? page_num / 2 : 0;
	}

	bw.client_width = client_width;
	
	var list = jQuery( '#bw_list' );
	
	if ( bw.inited && list[0] && bw.list_item_count_get() != list_item_count ) {
		if ( list.hasClass( 'bw_list_collapsed' ) ) {
			bw.list_collapse_refresh( list );
		}
		
		bw.anchor_set( 'L', 'p', parseInt( page_num ) )
		bw.filter_apply( false );
	}
	
	body.attr( 'class', classname );
	
	if ( fn ) fn();
};

/*
 * time to run our onready-events
 */
bw.onready_start = function () {
	if ( bw.debug ) console.debug( 'bw.onready_start()' );

	if ( bw.onready_callbacks.length > 0 ) {
		jQuery.each( bw.onready_callbacks, function( i, fn ){
			fn();
		});
	}
};

/*
 *  
 */
bw.onready = function ( fn ) {
	if ( bw.debug ) console.debug( 'bw.onready( ' + typeof fn + ' )' );
	
	if ( !bw.inited ) {
		bw.onready_callbacks.push( fn );
	}
	else {
		fn();
	}
};

/*
 * init anchors, containers, links, etc.
 */
bw.init = function () {
	if ( bw.debug ) console.debug( 'bw.init()' );
	
	bw.settings = {
		container: jQuery( '#bw_content' )
	};
	
	bw.placeholder_fallback();

	if ( bw.inited == undefined ) {
		bw.resolution_init(function(){
			if ( bw.anchor_exist( 'H', 'i' ) ) {
				bw.anchor_select( 'H', 'i', bw.anchor_get_value( 'H', 'i' )[0] );
			}
			
			bw.helpers();
			bw.inited = true;
			bw.anchor_watcher();
			bw.onready_start();
			bw.filter_apply( false );
			bw.search_init();
			
			jQuery( '.highslide-controls' )
				.live( 'mouseenter', function(){
					if ( !document.getElementById( 'highslide-controls-info' ) ) {
						jQuery( this ).append( '<div id="highslide-controls-info"><b>Tipp!</b><br/> Nutzen Sie die Pfeiltasten auf Ihrer Tastatur!' );
					}
				})
				.find( 'a' )
				.live( 'click', function(){
					window.setTimeout(function(){
						jQuery( '#highslide-controls-info' ).fadeOut();
					}, 650 );
				});
		});
		
		bw.menu_init();
		bw.anchor = window.location.hash;
		bw.anchors = bw.anchors_decode();
	}
};

/*
 * bind some usefull events, etc.
 */

bw.helpers = function () {
	if (jQuery.browser.msie) {
		jQuery('input[type="checkbox"]').live('click', function(){
			var checkbox = jQuery( this );
			
			checkbox.trigger('blur');
			
			jQuery( 'label[for="' + checkbox.attr( 'id' ) + '"]').live( 'click', function(){
				checkbox.trigger('blur');
			});
		});
	}
	
	document.write = function( string ){
		if ( !string ) return;
		
		jQuery( 'head:first' ).append( string );
	}

	document.onkeydown = function(e){
		var event = window.event ? window.event : e;
		
		// ignore shortcuts and pseudo-mouse-events
		if ( event.altKay !== false ) {
			return;
		}
		
		bw.keys_pressed.push( event );
		
		if ( !bw.settings || !bw.settings.list || !bw.settings.list.navigation ) return;
		
		switch( event.keyCode ) {
			case 27:
				if ( hs.getExpander() !== null && event.explicitOriginalTarget.id == 'hotel-detail-tab7' ) {
					if ( !confirm( 'Moechten Sie die Buchung wirklich abbrechen?' ) ) {
						return false;
					}
				}
			break;
			
			case 37:
				if ( hs.getExpander() === null ) {
					bw.settings.list.navigation.prev.trigger('click');
				}
			break;
			
			case 39:
				if ( hs.getExpander() === null ) {
					bw.settings.list.navigation.next.trigger('click');
				}
			break;
		}
	}

	document.onkeyup = function(e){
		var event = window.event ? window.event : e,
			tmp = [];
		
		jQuery.each( bw.keys_pressed, function( key, value ){
			if( value.keyCode == event.keyCode ) return;
			
			tmp.push( value )
		});
		
		bw.keys_pressed = tmp;
	};
};

/*
 * mark the dom element which controls the filter as selected or not 
 */
bw.filter_toggle = function ( element ) {
	if ( bw.debug ) console.debug( 'bw.filter_toggle( ' + element + ' )' );
	if ( !element ) return false;
	
	element = jQuery( element );
	
	if( element.hasClass( 'selected' ) ) {
		bw.filter_unselect( element );
	}
	else {
		bw.filter_select( element );
	}
	
	bw.anchors = bw.anchor_remove( 'L', 'p' );
	bw.filter_apply( true );
},

/*
 * mark the dom element which controls the filter as selected or not 
 */
bw.filter_unselect = function ( element ) {
	if ( bw.debug ) console.debug( 'bw.filter_unselect( ' + element + ' )' );
	
	jQuery( element ).removeClass( 'selected' );
};

/*
 * add a hotel to notices
 */
bw.notice_hotel_add = function( element, hotel, name ){
	if ( bw.debug ) console.debug( 'bw.notice_hotel_add( ' + element + ', ' + hotel + ', ' + name + ' )' );

	var cookie = bw.cookie_get( bw.cookie_name );
	
	if ( cookie == undefined ) {
		cookie = {};
	}
	
	if ( cookie[hotel] == undefined ) {
		cookie[hotel] = {
			name: name,
			pathname: window.location.pathname,
			items: {}
		};
	}
	
	bw.cookie_write( bw.cookie_name, cookie );
	bw.notice_layer_update();
};

/*
 * delete a hotel from notices
 */
bw.notice_hotel_delete = function( hotel ){
	if ( bw.debug ) console.debug( 'bw.notice_hotel_delete( ' + name + ' )' );
	
	var cookie = bw.cookie_get( bw.cookie_name );
	
	if ( cookie == undefined || cookie[hotel] == undefined ) {
		return false;
	}
	
	delete cookie[hotel];

	bw.cookie_write( bw.cookie_name, cookie );
	bw.notice_layer_update();
};

/*
 * add a hotel item (package, roomtype or program) to notices without animations
 */
bw.notice_hotel_item_add_clean = function( element, hotel, category, name, value, title ){
	bw.notice_hotel_item_add( element, hotel, category, name, value, title, false );
};

/*
 * add a hotel item (package, roomtype or program) to notices
 */
bw.notice_hotel_item_add = function( element, hotel, category, name, value, title, animate ){
	if ( bw.debug ) console.debug( 'bw.notice_hotel_item_add( ' + element + ', ' + hotel + ', ' + category + ', ' + name + ', ' + value + ', ' + title + ' )' );
	
	var cookie = bw.cookie_get( bw.cookie_name ),
		anchors = bw.anchors_decode();
		
	item_anchor = category + name + value;
	
	if (!bw.anchor_exist('H', anchors)) {
		anchors = bw.anchors_decode( window.location.hash );
	}

	anchors = bw.anchor_remove_uniques('H', anchors);
	
	if ( anchors[category] == undefined ) {
		anchors[category] = {};
	}
	
	anchors[category][name] = [ value ];
	
	if ( cookie == undefined || cookie[hotel] == undefined ) {
		return false;
	}
	
	cookie[hotel].items[item_anchor] = {
		name: title,
		pathname: window.location.pathname,
		anchor: bw.anchors_encode( anchors )
	}

	if ( animate !== false ) {
		bw.notice_item_animate( element, !bw.cookie_exist( bw.cookie_name ) );	
	}
	
	bw.cookie_write( bw.cookie_name, cookie );
	bw.notice_layer_update();
};

/*
 * delete a hotel item (package, roomtype or program) from notices
 */
bw.notice_hotel_item_delete = function( hotel, item ) {
	if ( bw.debug ) console.debug( 'bw.notice_hotel_item_delete( ' + hotel + ', ' + item + ' )' );
	if ( !hotel || !item ) return false;
	
	var cookie = bw.cookie_get( bw.cookie_name );
	
	if ( cookie != undefined && cookie[hotel] && cookie[hotel].items[item] ) {
		delete cookie[hotel].items[item];
	}
	
	bw.cookie_write( bw.cookie_name, cookie );
	bw.notice_layer_update();
};

/*
 * let the "merken"-link fly around :)
 * if it is the first note, scroll to the top of the window, open the notice layer for a short time and scroll back
 */
bw.notice_item_animate = function( element, scroll ) {
	if ( bw.debug ) console.debug( 'bw.notice_item_animate( ' + element + ' )' );
	
	element = jQuery( element );
	
	var notice_link = jQuery( '#bw_notice_link' ),
		notice_link_offset = notice_link.offset(),
		element_offset = element.offset();
	
	var spacer = element
		.parent()
		.css({
			width: element.outerWidth()
		});

	element.css({
			top: element_offset.top,
			left: element_offset.left,
			height: element.height(),
			width: element.width(),
			position: 'absolute',
			'z-index': 1000
		})
		.appendTo( 'body' )
		.animate({ top: element_offset.top - 20, left: element_offset.left - 50 }, bw.speed, null, function(){
				if ( scroll ) {
					var scroll_position = jQuery( document ).scrollTop();
					
					jQuery( 'html,body' ).animate({ scrollTop: 0 }, scroll_position / 2, 'easeOutExpo', function(){
						element.animate({ top: notice_link_offset.top, left: notice_link_offset.left }, 1200, 'easeOutExpo', function(){
							element.fadeOut( 'slow', function(){
								jQuery( this ).remove();
							});
							
							window.setTimeout(function(){
								bw.notice_layer_show();
								spacer.remove();
								
								window.setTimeout(function(){
									bw.notice_layer_hide();
									
									window.setTimeout(function(){
										jQuery( 'html,body' ).animate({ scrollTop: scroll_position }, bw.speed, null );
									}, 750 );
								}, 1300 );
							}, 550 );
						});
					});
				}
				else {
					element.animate({ top: notice_link_offset.top - jQuery( document ).scrollTop(), left: notice_link_offset.left }, 1200, 'easeOutExpo', function(){
						element.fadeOut( 'slow', function(){
							jQuery( this ).remove();
						});
						
						window.setTimeout(function(){
							spacer.remove();
						}, 550 );
					});
				}
			}
		);
};

/*
 * update content of the notice layer
 */
bw.notice_layer_update = function(){
	if ( bw.debug ) console.debug( 'bw.notice_layer_update()' );

	var notices = bw.cookie_get( bw.cookie_name ),
		layer = jQuery( '#bw_notice_layer_content' ).empty();

	if ( bw.isEmptyObject( notices ) ) {
		layer.append( '<div class="bw_notice_layer_empty">Sie haben sich noch nichts vorgemerkt.<div class="clearfix"></div></div>' );
	}
	else {
		jQuery.each( notices, function( hotel_anchor, hotel ){
			var container = jQuery( document.createElement( 'div' ) )
				.addClass( 'bw_notice_layer_group' );
	
			container.append( bw.notice_layer_hotel_add( hotel_anchor, hotel ) );
	
			jQuery.each( notices[hotel_anchor].items, function( item_anchor, item ){
				container.append( bw.notice_layer_hotel_item_add( hotel_anchor, item_anchor, item ) );
			})
			
			layer.append( container );
		});
	}
	
	layer.append( '<div><a class="bw_notice_layer_close" href="#" onclick="return false;">Merkzettel schließen</a><div class="clearfix"></div></div>' );
};

/*
 * slide toggle replacement
 */
bw.notice_layer_toggle = function(){
	if ( bw.debug ) console.debug( 'bw.notice_layer_toggle()' );

	if ( jQuery( '#bw_notice_layer' ).is( ':visible' ) ) {
		bw.notice_layer_hide();
	}
	else {
		bw.notice_layer_update();
		bw.notice_layer_show();
	}
};

/*
 * show the notice layer
 */
bw.notice_layer_show = function(){
	if ( bw.debug ) console.debug( 'bw.notice_layer_show()' );

	jQuery( '#bw_notice_layer' ).slideDown();
};

/*
 * hide the notice layer
 */
bw.notice_layer_hide = function(){
	if ( bw.debug ) console.debug( 'bw.notice_layer_hide()' );

	jQuery( '#bw_notice_layer' ).fadeOut();
};

/*
 * add a hotel to the notice layer
 */
bw.notice_layer_hotel_add = function( anchor, hotel ){
	if ( bw.debug ) console.debug( 'bw.notice_layer_hotel_add( ' + anchor + ', ' + hotel + ' )' );
	
	var div = jQuery( document.createElement( 'div' ) )
		.addClass( 'bw_notice_layer_head' )
		.append( jQuery( document.createElement( 'a' ) )
			.addClass( 'bw_notice_layer_hotel' )
			.html( hotel.name )
			.attr( 'href', hotel.pathname + '#' + anchor )
			.bind( 'click', function(){
				if ( window.location.pathname == hotel.pathname ) {
					bw.scroll = true;
					bw.nodelay(function(){
						window.location.hash = anchor;
						bw.scroll_to_current();
					});
					bw.notice_layer_hide();
					
					return false;
				}
				
				window.location = hotel.pathname + '#' + anchor;
			})
		)
		.append(
			jQuery( document.createElement( 'a' ) )
				.addClass( 'bw_notice_layer_remove' )
				.text( 'löschen' )
				.bind( 'click', function(){
					bw.notice_hotel_delete( anchor );
					
					return false;
				})
				.bind( 'mouseenter', function(){
					jQuery( this )
						.closest( '.bw_notice_layer_group' )
						.addClass( 'bw_notice_layer_group_delete' );
					
					return false;
				})
				.bind( 'mouseleave', function(){
					jQuery( this )
						.closest( '.bw_notice_layer_group' )
						.removeClass( 'bw_notice_layer_group_delete' );
					
					return false;
				})
		);
	
	return div;
};

/*
 * add a hotel item (package, roomtype, program) to the notice layer
 */
bw.notice_layer_hotel_item_add = function( hotel, anchor, item ){
	if ( bw.debug ) console.debug( 'bw.notice_layer_hotel_item_add( ' + hotel + ', ' + anchor + ', ' + item + ' )' );

	var div = jQuery( document.createElement( 'div' ) )
		.addClass( 'bw_notice_layer_item' )
		.append(jQuery( document.createElement( 'a' ) )
			.addClass( 'bw_notice_layer_link' )
			.text( item.name )
			.attr( 'href', item.pathname + '#' + item.anchor )
			.bind( 'click', function(){
				if ( window.location.pathname == item.pathname ) {
					bw.scroll = true;
					bw.nodelay(function(){
						window.location.hash = item.anchor;
						bw.scroll_to_current();
					});
					bw.notice_layer_hide();
					
					return false;
				}
				
				window.location = item.pathname + '#' + item.anchor;
			})
		)
		.append(
			jQuery( document.createElement( 'a' ) )
				.addClass( 'bw_notice_layer_remove' )
				.text( 'löschen' )
				.bind( 'click', function(){
					bw.notice_hotel_item_delete( hotel, anchor );
					
					return false;
			})
			.bind( 'mouseenter', function(){
				jQuery( this )
					.closest( '.bw_notice_layer_item' )
					.addClass( 'bw_notice_layer_item_delete' );
				
				return false;
			})
			.bind( 'mouseleave', function(){
				jQuery( this )
					.closest( '.bw_notice_layer_item' )
					.removeClass( 'bw_notice_layer_item_delete' );
				
				return false;
			})
		);

	return div;
};

/*
 * check if a cookie with the given name already exusts
 */
bw.cookie_exist = function( name ) {
	if ( bw.debug ) console.debug( 'bw.cookie_exist()' );
	
	return ( typeof jQuery.cookie( name ) == 'string' );
};

/*
 * writes the given value into a cookie
 */
bw.cookie_write = function( name, value ) {
	if ( bw.debug ) console.debug( 'bw.cookie_write( ' + name + ', ' + value + ' )' );
	
	/**
	 * nodelay?
	 */
	
	bw.cookie[name] = value;
	bw.nodelay(function(){
		var path = '/' + ( bw.settings.language ? bw.settings.language + '/' : '' );
		jQuery.cookie( name, bw.json_encode( value ), { expires: 31, path: path, domain: window.location.host, secure: false });
	});
};

/*
 * return the content of a cookie
 */
bw.cookie_get = function( name ) {
	if ( bw.debug ) console.debug( 'bw.cookie_get( ' + name + ' )' );
	
	if ( bw.cookie[name] != undefined ) {
		return bw.cookie[name];
	}
	
	var value = jQuery.cookie( name );

	if ( value != null ) {
		value = bw.json_decode( value );
	}
	
	bw.cookie[name] = value;
	
	return value;
};

/*
 * delete the cookie with the given name
 */
bw.cookie_delete = function( name ) {
	if ( bw.debug ) console.debug( 'bw.cookie_delete( ' + name + ' )' );
	
	jQuery.cookie( name, false, { expires: -1 });
};

/*
 * convert the given object into json string
 */
bw.json_encode = function( data ) {
	if ( bw.debug ) console.debug( 'bw.json_encode( ' + data + ' )' );
	
	if ( JSON != undefined && JSON.stringify != undefined ) {
		return JSON.stringify( data );
	}

	return jQuery.json.encode( data );
};

/*
 * convert the given json string into an object
 */
bw.json_decode = function( json ) {
	if ( bw.debug ) console.debug( 'bw.json_decode( ' + json + ' )' );
	if ( !json ) return false;
	
	if ( JSON != undefined && JSON.parse != undefined ) {
		return JSON.parse( json );
	}

	return jQuery.json.decode( json );
};

bw.isEmptyObject = function( obj ) {
	if ( bw.debug ) console.debug( 'bw.isEmptyObject( ' + obj + ' )' );
	
	for ( var name in obj ) {
		return false;
	}
	return true;
};

bw.placeholder_fallback = function( selector ){
	if ( bw.debug ) console.debug( 'bw.placeholder_fallback()' );
	if ( !selector ) selector = 'textarea[placeholder], input[placeholder], select[placeholder]';

	jQuery( selector ).each(function(){
		var input = jQuery( this ),
			tagname = this.tagName.toString().toLowerCase();
		
		input
			.bind( 'focus', function(){
				input.removeClass('placeholder')
				
				if ( tagname != 'select' && input.val() == input.attr( 'placeholder' ) ) {
					input.val('')
				}
				
			})
			.bind( 'change', function(){
				input.trigger( 'blur' )
			})
			.bind( 'blur', function(){
				if ( !input.hasClass( 'hasDatepicker' ) && ( input.val() == '' || input.val() == 0 ) ) {
					input	
						.addClass( 'placeholder' )
						.val( tagname == 'select' ? 0 : input.attr( 'placeholder' ) );
				}
			})
			.each(function(){
				if ( input.val() == '' || input.val() == 0 ) {
					input	
						.addClass( 'placeholder' )
						.val( tagname == 'select' ? 0 : input.attr( 'placeholder' ) );
				}
				
				if ( input.attr( 'autocomplete' ) ) {
					bw.autocomplete( input );
				}
			});
	});
	
	jQuery.datepicker.setDefaults({
		onClose: function(dateText, inst) {
			var input = jQuery( this );
			
			if ( !input.attr( 'placeholder' ) ) return;

			if ( dateText.length == 0 || input.val().length == 0 ) {
				input
					.addClass('placeholder')
					.val( input.attr( 'placeholder' ) );
			}
			else {
				input.removeClass('placeholder');
			}
		},
		onSelect: function(dateText, inst) {
			var input = jQuery( this );
			
			if ( !input.attr( 'placeholder' ) ) return;

			if (dateText.length == 0 || input.val().length == 0 ) {
				input.addClass('placeholder');
			}
			else {
				input.removeClass('placeholder');
			}
		}
	});
};

bw.request_form_submit = function( submit ){
	if ( bw.debug ) console.debug( 'bw.request_form_submit( ' + submit + ' )' );
	
	var form = jQuery( submit ).parents( 'form:first' );
	
	bw.form_submit( form, { ajax: true, validate: true, layout: 'small' }, function( response ){
		form
			.parent()
			.html( response );
			
		bw.placeholder_fallback();
		bw.scroll_to( '#detail_contents' );
	});
};

bw.request_market_form_submit = function( form ){
	if ( bw.debug ) console.debug( 'bw.request_market_form_submit( ' + form + ' )' );
	
	form = jQuery( form );
	
	var states_selected = jQuery( '#bw_request_market_regions' ).find( 'input:checked' ).size();

	if ( !states_selected ) {
		jQuery( '#bw_request_market_submit_info' )
			.show()
			.delay( 5000 )
			.fadeOut( 'slow' );
		
		return;
	}
	
	bw.form_submit( form, { ajax: false, validate: true, layout: 'small' }, function( response ){
		form
			.parent()
			.html( response );
			
		bw.placeholder_fallback();
		bw.scroll_to( '#detail_contents' );
	});
};

bw.request_market_states_toggle = function( element, fn ){
	if ( bw.debug ) console.debug( 'bw.request_market_states_toggle( ' + element + ' )' );

	var country = jQuery( element ),
		container = country
			.parent()
			.next()
			.next(),
		states = container.find( 'input' ),
		states_selected = states.filter( ':checked' ).size();
		
	delete element;
	
	if ( states_selected > 0 && states.size() != states_selected ) {
		country.attr( 'checked', 'checked' );
		states.attr( 'checked', 'checked' );
	}
	else {
		states
			.attr( 'checked', !container.toggleClass( 'hidden' ).hasClass( 'hidden' ) )
			.unbind( 'change' )
			.bind( 'change', function(){
				if ( states.filter( ':checked' ).size() == 0 ) {
					container.addClass( 'hidden' );
				}
				
				if ( !jQuery( this ).attr( 'checked' ) ) {
					country.removeAttr( 'checked' );
				}
				else if ( states.size() == states.filter( ':checked' ).size() ) {
					country.attr( 'checked', 'checked' );
				}
				
				bw.request_market_hotel_count_get();
			});
	}
	
	if ( fn ) fn();
};

bw.request_market_hotel_count_get = function(){
	if ( bw.debug ) console.debug( 'bw.request_market_hotel_count_get()' );

	var uri_hotel_count = 'request.php?page=0.hotel_count&form[request][request_criterion]=1';
	
	jQuery( '#bw_request_market_regions, #bw_request_market_indicators' )
		.find( 'input[type="checkbox"]:checked' )
		.each(function(){
			var checkbox = jQuery( this );
			
			uri_hotel_count += '&' + checkbox.attr( 'name' ) + '=' + checkbox.attr( 'value' );
		})

	bw.content_load( { uri: bw.url_validate(uri_hotel_count), dataType: 'json' }, function( response ){
		jQuery( '#bw_request_market_hotel_count' )
			.toggleClass( 'disabled', !response.hotel_count )
			.find( '#bw_request_market_hotel_count_text' )
			.text( response.hotel_count )
			.end()
			.children()
			.eq( response.hotel_count ? 1 : 0 )
			.addClass( 'hidden' )
			.end()
			.eq( response.hotel_count ? 0 : 1 )
			.removeClass( 'hidden' );

		if (response.hotel_count) {
			return
		}
	});
};

bw.menu_init = function(){
	if ( bw.debug ) console.debug( 'bw.menu_init()' );
	
	bw.menu = jQuery( '#bw_menu_left_list' );
	
	bw.menu
		.find( 'a' )
		.bind( 'click', function(){
			if ( bw.keys_pressed.length != 0 ) return;

			jQuery( 'body' ).removeClass( 'ready' );
			
			bw.menu
				.children()
				.filter( '.bw_menu_list_item_active' )
				.removeClass( 'bw_menu_list_item_active' );

			jQuery( this )
				.parent()
				.parent()
				.addClass( 'bw_menu_list_item_active' );
		});
}

bw.autocomplete = function( selector ){
	if ( bw.debug ) console.debug( 'bw.autocomplete(' + selector + ')' );
	
	if ( !selector ) selector = 'input[autocomplete="true"]';
	
	jQuery( selector )
		.each(function(){
			var element = jQuery( this  ),
				values = ( element.attr( 'rev' ) ? element.attr( 'rev' ).split( ',' ) : [] ),
				source = [];
				
				
			jQuery.each( values, function( key, value ){
				source.push({
					value: key,
					label: value
				})
			});
			
			element.autocomplete({
					source: source,
					focus: function(event, ui) {
						element.val(ui.item.label);
						return false;
					},
					select: function(event, ui) {
						element.val(ui.item.value);
						return false;
					}
				});
		});
}

bw.form_validate_newsletter_subscribe = function( form ){
	if ( bw.debug ) console.debug( 'bw.form_validate_newsletter_subscribe(' + form + ')' );
	
	var form = jQuery( form );
	
	if ( !form[0] ) return false;
	
	var errors = [],
		error_container = jQuery('#bw_newsletter_signup_errors').addClass( 'hidden' ),
		elements = bw.form_data_get_elements( form );
	
	jQuery( elements ).each(function(){
		var element = jQuery( this );

		if ( element.attr( 'type' ) != 'hidden' && ( !element.val() || element.val().length == 0 ) ) {
			errors.push( element );
		}
	});
	
	if (errors.length > 0) {
		var error_container_span = error_container.find('span:first').empty();
		
		error_container.removeClass( 'hidden' );
		
		jQuery.each(errors, function(i){
			var element = jQuery(this),
				placeholder = element.attr('placeholder') || element.parent().attr('placeholder');
			
			if ( placeholder ) {
				error_container_span.append(
					jQuery(document.createElement('span')).html( placeholder + (i < elements.length ? ', ' : ''))
				);
				
				if ( element[0].tagName.toLowerCase() != 'option' ) {
					element.val( placeholder );
				}
			}
		});

		return false;
	}
	else {
		bw.form_submit(form, { ajax: true, validate: false }, function( response ){
			form.replaceWith( jQuery( response ).find( 'h1:first' ).html() );
			jQuery( '#bw_newsletter_signup_form_submit' ).remove();
		});
	}
}