// Metroseeq namespace
var mesq = mesq || {};

// Global constants
var AJAX_LOADER_IMG = 'themes/mesq/images/ajax-loader.gif';
var CONVERT_KM_MILES = 0.62137119;
var CONVERT_MILES_KM = 1.609344;
var MINIMARKER_IMG = "themes/mesq/images/marker-red-mini.png";
var MINIMARKER_SHADOW_IMG = "themes/mesq/images/marker-shadow-mini.png";
var MARKER_FEATURED_IMG = "themes/mesq/images/marker_red-featured.png";
var MARKER_NORMAL = "themes/mesq/images/marker-normal.png";
var MARKER_NORMAL_HOVER = "themes/mesq/images/marker-normal-hover.png";
var MARKER_DEALS = "themes/mesq/images/marker-deals.png";
var MARKER_DEALS_HOVER = "themes/mesq/images/marker-deals-hover.png";
var MARKER_SHADOW = "themes/mesq/images/marker-shadow.png";
var MARKER_CLUSTER = "themes/mesq/images/markers/marker-cluster.png";
var MARKER_CLUSTER_SHADOW = "themes/mesq/images/markers/marker-cluster-shadow.png";
var REDRAW_DELAY_SECS = 500;

var LIGHTWINDOW_OPTIONS =  {
	resizeSpeed: 9,
	hideFlash: true
};

var PROTOTIP_OPTIONS = {
	showOn: 'click', 
	hideOn: 'click',
	hideAfter: 2,
	fixed:true,
	closeButton: true,
	hook:{target: 'bottomRight', tip: 'topLeft'}
};

/**
 * Base application used to instanciate the map,
 * and provide a feedback framework for errors.
 */
mesq.App = Class.create();

// instance methods
Object.extend(mesq.App.prototype, {
  
  	// objects
  	map: null,
  	list: null,
  	dealList: null,
  	wheelOfMeals: null,
  	placeListManager: null,
  	myLightWindow: null,
  	prefCookieJar: null, // CookieJar object
  	
  	// strings
  	msgBrowserCompatibility: "" +
  			'<h2>Please upgrade your browser</h2>' +
  			'<p>Your browser is not supported by Metroseeq, please consider upgrading.</p>' +
  			'<p><a href="http://browsehappy.com/" title="Browse Happy: Switch to a safer browser today"><img src="http://browsehappy.com/buttons/bh_185x75.gif" alt="Browse Happy logo" width="185" height="75"></a></p>' +
  			'<p style="margin-top: 3em;">We\'re sorry for any inconvenience!</p>',
  	msgRequestError: "Request failed - please try again.",
  	
  	// config
  	prefCookieDays: 365,
  	
  	// debug
  	debug: false,
  	debugprofile: false,
  	
	initialize: function() {
	  	// initiate cookie jar
 		this.prefCookieJar = new CookieJar({
 			expires: this.prefCookieDays * 24 * 60 * 3600,
 			path:'/'
 		});
	  	
	  	this.debug = this.debug || document.location.href.toQueryParams().debug_js;
	  	this.debugprofile = this.debugprofile || document.location.href.toQueryParams().debug_profilejs;
	},
	
	run: function() {
		
		// ensure compatibility with google maps api
		if(typeof(GBrowserIsCompatible) != 'undefined' && !GBrowserIsCompatible()) {
	  		this.compatibilityError();
	  		return false;
	  	}
	  	
	  	// browser detection is evil, but in this case we can't detect feature-capabilities
	  	// IE6 is simply to slow to render metroseeq in a useable way (~10x slower than FF2 actually)
	  	if(Prototype.Browser.IE && Prototype.Browser.Version.IE < 7 && !this.debug) {
	  		this.compatibilityError();
	  		return false;
	  	}
		
		// init searchform
		if($('UserSearch')) {
			this.searchForm = new mesq.SearchForm($$('#UserSearch form')[0]);
		}

		// lightwindow
		if(typeof(lightwindow) != 'undefined') this.myLightWindow = new lightwindow(LIGHTWINDOW_OPTIONS);

		// make popup links
		if($$('body').first().hasClassName('popup')) {
			this.alterPopupLinks();
		}
		
		// only create map on prepared pages
		if($('PlaceMap') && $('Results')) {
			// TODO more modular components (less inter-references)
			this.map = new mesq.PlaceMap($('PlaceMap').down('.mapInner'));
			this.list = new mesq.List($('Results'), this.map);
			this.map.setList(this.list);
			
			// only search when items are not pre-set (e.g. in seeqlist-view)
			if(document.getElementById('ResultsStopSearchContainer').className!=''){
				//This should stop progressive searching for seeqlists.  You'll get a javascript error if you dont...
				this.map.enableStopProgressiveSearch();
			}
			//this.map.enableStopProgressiveSearch();
			
			if(this.map.searchEnabled()) this.map.search();
			/*
			// TODO Triggered too fast before DOM is fully loaded 
			if(this.isPrint()) {
				Event.observe(this.map.container, 'Map:resultsloaded', this.printWindow.bind(this));
			}
			 */
		}
		
		// only create map on prepared pages
		if($('DealMap') && $('DealTypeSelection')) {
			this.map = new mesq.DealMap($('DealMap').down('.mapInner'));
			this.dealTypeSelection = new mesq.DealTypeSelection($('DealTypeSelection'), this.map);
			if($('Results')) {
				this.list = new mesq.List($('Results'), this.map);
				this.map.setList(this.list);
			}
			// only search when items are not pre-set (e.g. in seeqlist-view)
			if(this.map.searchEnabled()) this.map.search();
		}

		// only create map on prepared pages
		if($('MiniMap')) {
			var placeData = {
				'lat': Number($$('.placeDetail .latitude')[0].innerHTML),
				'lng': Number($$('.placeDetail .longitude')[0].innerHTML),
				'ID': Number($$('.placeDetail')[0].id.replace(/Place/,''))
			};
			this.map = new mesq.MiniMap($('MiniMap').down('.mapInner'), placeData);
		}
		
		// deal list
		if($('DealListHolder')) {
			this.dealList = new mesq.DealList($('DealListHolder').down('.container'), this.list, this.map);
		}
		
		// the other deal list (found on restaurant detail pages)
		if($('BusinessData')){
			$('BusinessData').select('.deal').each(function(el) {
				new mesq.Deal(el);
			}.bind(this));
		}
		
		// place list
		if($('PlaceListManager')) {
			this.placeListManager = new mesq.PlaceListManager($('PlaceListManager'));
		}
		
		// prototip
		if(typeof(Tips) != 'undefined') {
			Tips.zIndex = 900; // needs to be lower than lightwindow overlay
			Tips.fixIE = false; // we're not using <select> in the tooltips, the iframe-shim messes up links
		}
		
		// choose city
		if($('ChooseDefaultCity')) {
			new Tip(
				'ChooseDefaultCityLink',
				$('ChooseDefaultCity'),
				Object.extend(PROTOTIP_OPTIONS, {
					hideOn: {element: '.close', event: 'click'}, 
					hook:{target: 'bottomLeft', tip: 'topLeft'}
				})
			);
		}
		
		// behaviour
		window.setupForBehaviour = true;
		var rules = {
			'a[rel]': {
				initialize: function() {
					if(this.hasClassName('lightwindow_action') || this.hasClassName('prototip-custom')) return true;
					
					this.tip = new Tip(
						this, 
						this.rel, 
						Object.extend(PROTOTIP_OPTIONS, {
							showOn: 'mouseover',
							hideOn: 'mouseout',
							hook:{target: 'bottomRight', tip: 'topRight'},
							closeButton: false,
							fixed: false,
							delay: 0
						})
					);		
				}
			},
			'a.lightwindow': {
				initialize: function() {
					//this.href += '?popup=1';
				}
			},
			'a.lightwindow_action_deactivate_iframe':{
				onclick: function(e) {
					window.top.app.myLightWindow.deactivate();
					e.stop();
				}
			},
			'#MemberLocations a':{
				onclick: function(e) {
					var el = Event.element(e);
					var params = el.href.toQueryParams();
					if(params.where) $('UserSearch').down('input[name=where]').value = params.where.urldecode().stripTags();
					Event.stop(e);
					return false;
				}
			},
			'.lightwindow': { 
				initialize: function() {}
			}
		};
		
		Behaviour.register(rules);
		Behaviour.apply();
		
		if(typeof(lightwindow) != 'undefined') this.myLightWindow.ss_refreshLinks();
		
		this.setupMemberLocations();
		
	},
	
	refreshMemberLocations: function() {
		new Ajax.Updater(
			{success: 'MemberLocations'},
			'Member/getmemberlocations',
			{
				onFailure: this.ajaxErrorHandler,
				onComplete: function(response) {
					Behaviour.reapply();
				}.bind(this)
			}
		);
		
	},
	
	setupMemberLocations: function() {
		if($('MemberLocationsSearchFormLink')) {
			this.tip = new Tip(
				$('MemberLocationsSearchFormLink'),
				$('MemberLocationsSearchForm'),
				Object.extend(PROTOTIP_OPTIONS, {
					hideOn: {element: '.close', event: 'click'}, 
					hook:{target: 'bottomLeft', tip: 'topLeft'},
					closeButton: true
				})
			);
		}
		if($('MemberLocationsHeaderLink')) {
			this.tip = new Tip(
				$('MemberLocationsHeaderLink'),
				$('MemberLocationsHeader'),
				Object.extend(PROTOTIP_OPTIONS, {
					hideOn: {element: '.close', event: 'click'}, 
					hook:{target: 'bottomRight', tip: 'topRight'},
					closeButton: true
				})
			);
		}
	},
	
	alterPopupLinks: function() {
		$$('a').each(function(el) {
			if(el.href && el.href.length > 0) {
				el.href += (el.href.indexOf('?')) ? '&popup=1' : '?popup=1';
			}
		});
	},
	
	compatibilityError:function() {
		$('Layout').replace('<div id="CompatibilityError"><div class="message">' + this.msgBrowserCompatibility + '</div></div>');	
	},
	
	setPref: function(key, value) {
		this.prefCookieJar.put(key, value);
	},
	
	getPref: function(key) {
		return this.prefCookieJar.get(key);
	},
	
	ajaxErrorHandler: function(response) {
		mesq.App.errorMessage(this.msgRequestError);
	},
	
	printWindow: function(e) {
		window.print();
	},
	
	isPrint: function() {
		return document.location.href.toQueryParams().print;
	},
	
	isLoggedIn: function() {
		return $(document.body).hasClassName('loggedIn');
	},
	
	baseURL: function() {
		return $$('base').first().href;
	}
});

// static methods
mesq.App.errorMessage = function(msg, level) {
	if(!level) level = "topError";
	
	$$('body').first().insert({
		before:"<p class=\"" + level.stripTags() + "\">" + msg.stripTags() + "</p>"
	});
};


/**
 * Initialization and library loading (with or without google maps)
 */

document.observe("dom:loaded", function() {
//Event.observe(window,'load', function() {
	window.app = new mesq.App();
	app.run();
});

Event.observe(window, 'load', function() {
	// wheel of meals
	if($('WheelOfMeals')) {
		window.app.wheelOfMeals = new mesq.WheelOfMeals($('WheelOfMeals'));
	}
});
Event.observe(window, 'unload', function() {
	window.app = null;
	mesq = null;
	if(typeof(GUnload) != 'undefined') GUnload();
});

/**
 * Lightwindow extension for more flexible
 * link handling/refreshing.
 * @see __processLinks()
 */
if(typeof lightwindow != 'undefined') {
	lightwindow.prototype.ss_refreshLinks = function() {
		var links = $$('.'+this.options.classNames.standard);
		links.each(function(link) {
			
			// HACK Can't properly unregister eventhandler due to dynamic parameters in binding
			Event.stopObserving(link, 'click'); 
			Event.observe(link, 'click', this.activate.bindAsEventListener(this, link), false);
			link.onclick = function() {return false;};		
		}.bind(this));	
	}
} 
