/* 10 years later IE doesn't have indexOf ... congrats MS! */
if(!Array.indexOf){
	Array.prototype.indexOf = function(obj) {
		for(var i=0; i<this.length; i++){ if(this[i]==obj){ return i; } }
		return -1;
	}
}

function SearchCriteria() {
	this.ne_lat = null;
	this.ne_lng = null;
	this.sw_lat = null;
	this.sw_lng = null;

	this.zoom = null;

	this.countries = [];
	this.technology_types = [];
	this.location_types = [];
	this.search_string = "";
	this.pixel_width = 1600;

	this.xmlrpc_endpoint = gSettings.xmlrpc_filter_endpoint;

	this.searchStringLocation = null;
}

SearchCriteria.prototype.clear = function() {
	this.ne_lat = null;
	this.ne_lng = null;
	this.sw_lat = null;
	this.sw_lng = null;

	this.zoom = null;

	this.countries = [];
	this.technology_types = [];
	this.location_types = [];
	this.pixel_width = 1600;
}

SearchCriteria.prototype.reloadSearchCriteria = function(mapControl) {
	this.location_types = mapControl.getSelectedLocationTypes();
	this.technology_types = mapControl.getSelectedTechnologyTypes();
	this.zoom = mapControl.getCurrentZoomLevel();
	this.search_string = mapControl.getSearchString();
	bounds = mapControl.getBounds();
	this.ne_lat = bounds[0];
	this.ne_lng = bounds[1];
	this.sw_lat = bounds[2];
	this.sw_lng = bounds[3];
	this.pixel_width = mapControl.getMapWidth();
}

SearchCriteria.prototype.getSearchUrl = function() {
	str = "[SearchCriteria.getSearchUrl]Refreshing points in area [(" + this.ne_lat + "," + this.ne_lng + "),(" + this.sw_lat + "," + this.sw_lng + ")][" + this.zoom + "]";
	//log.debug(str);
	url = this.xmlrpc_endpoint;
	url += "?zoom=" + this.zoom + "&ne_lat=" + this.ne_lat + "&ne_lng=" + this.ne_lng + "&sw_lat=" + this.sw_lat + "&sw_lng=" + this.sw_lng;
	url += "&pixel_width=" + this.pixel_width;
	for( i = 0; i < this.countries.length; i++ ) {
		url += "&c=" + this.countries[i];
	}

	if(typeof(this.technology_types) == "number") {
		url += "&tt=" + this.technology_types;
	} else {
		for( i = 0; i < this.technology_types.length; i++ ) {
			url += "&tt=" + this.technology_types[i];
		}
	}

	if(typeof(this.location_types) == "number") {
		url = url+ "&lt=" + this.location_types;
	} else {
		for( i = 0; i < this.location_types.length; i++ ) {
			url = url+ "&lt=" + this.location_types[i];
		}
	}

	url += "&search_string=" + this.search_string;
	return url;
}


SearchCriteria.prototype.setEndpoint = function(url) {
	this.xmlrpc_endpoint = url;
}

function constructSearchUrl(options) {
	var url = "search_string=" + options.search_string
		+ "&zoom=" + options.map.zoom
		+ "&ne_lat=" + options.map.ne_lat + "&ne_lng=" + options.map.ne_lng
		+ "&sw_lat=" + options.map.sw_lat + "&sw_lng=" + options.map.sw_lng
		+ "&pixel_width=" + options.map.pixel_width
		+ "&search_location=" + options.search_location
		+ "&center_lat=" + options.center_lat
		+ "&center_lng=" + options.center_lng;

	for(var i = 0; i < options.technology_types.length; i++)
		url += "&tt=" + options.technology_types[i];

	for(var i = 0; i < options.location_types.length; i++)
		url += "&loc_type=" + options.location_types[i];
	return url;
}


/**
 * Logging class, wrapping around Maps API logging - GLog.
 * @param enabled true means debugging is enabled(console etc.)
 * @return Nothing
 */
function Logging(enabled) {
	this.enabled = enabled;
};


/**
 * Debug method for logging, logs a message in blue color into debugging window.
 * if debug is enabled.
 * @param message Message to log
 */
Logging.prototype.debug = function(message) {
	if(!this.enabled) return;
	GLog.write(message, '#606060');
};


/**
 * Debug method for logging, logs a message in blue color in debugging window,
 * if debug is enabled.
 * @param message Message to log
 */
Logging.prototype.warn = function(message) {
	GLog.write(message, '#0000FF');
};


/**
 * Debug method for logging, logs a message in orange color in debugging window,
 * if in debug mode.
 * Additionaly displays an alert with message, no matter of debugging mode.
 * @param message Message to log
 */
Logging.prototype.fatal = function(message) {
	if(this.enabled) {
		GLog.write(message, '#FF0000');
	}
	alert(message);
};


/**
 * Debug method for logging, logs a message in blue color into debugging window.
 * if debug is enabled.
 * @param message Message to log
 */
Logging.prototype.logUrl = function(url) {
	if(!this.enabled) return;
	GLog.writeUrl(url);
};


/**
 * http://blog.stevenlevithan.com/archives/faster-trim-javascript
 * @param str String to trim
 * @return Trimmed string
 */
function trim(str) {
	var	str = str.replace(/^\s\s*/, ''),
		ws = /\s/,
		i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}


function randomString(size) {
	var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var randomstring = '';
	for (var i=0; i<size; i++) {
		var rnum = Math.floor(Math.random() * chars.length);
		randomstring += chars.substring(rnum,rnum+1);
	}
	return randomstring;
}


function AIconManager() {
	/**
	 * iconCache[lt][tt] = GIcon();
	 */
	this.iconCache = {};
	this.groupIconCache = {};

	this.baseURL = gSettings.icon_base_url + "var/icons/markers/";
	this.baseURLSymbols = gSettings.icon_base_url + "var/icons/small/";
}

/**
 * @param location_id Integer If -1 group.png is returned because location is a group, otherwise icon is calculated.
 * @param lt_id Integer, locations_types.ID
 * @param tt_ids String with one or more technology_types.ID separated by comma. If more than one, 'lt_id'_group.png is returned.
 * @return An icon for the marker of type GIcon.
 */
AIconManager.prototype.getGoogleIcon = function(location_id, lt_id, tt_ids, selected_lt, g_p) {
	if(location_id != -1 && tt_ids == "") {
		log.warn("This location has no technology category set! ID=" + location_id);
	}
	//For groups
	if(location_id == -1) {
		//location_id == -1 => Group icon
		//	selected_lt_id.length == 1 => Group icon colored in lt_id
		imageName = ""
		if(selected_lt.length == 1) {
			//Return the group icon colored as (single one) selected location type
			imageName = selected_lt[0] + "_group/" + selected_lt[0] + "_group_" + (g_p < 1000 ? g_p + ".png" : "1000.png");
		}
		else {
			//We have multiple LT, return default (-1) group image
			imageName = "-1_group/-1_group_" + (g_p < 1000 ? g_p + ".png" : "1000.png");
		}
		iconURL = this.baseURL + imageName;
		if(this.groupIconCache[iconURL]) {
			return this.groupIconCache[iconURL];
		} else {
			var gicon = new GIcon(G_DEFAULT_ICON)
			gicon.image = iconURL;
			gicon.iconSize = GSize(34,36);
			gicon.shadow = null;
			this.groupIconCache[iconURL] = gicon;
			return gicon;
		}
	}
	//Otherwise
	tt = -1;
	try {
		tt_arr = tt_ids.split(",");
		if(tt_arr.length == 1) {
			if( tt_arr[0] != '')
				tt = parseInt(tt_arr[0]);
			else
				throw "[AIconManager.getGoogleIcon]Invalid Technology category string! " + tt_ids;
		}
		else tt = -2; //Groupped technology categories
	} catch(e) {};
	return this.cacheLookup(lt_id, tt);
}

AIconManager.prototype.getIconURL = function(lt_id, tt_id) {
	return this.baseURL + lt_id + "_" + tt_id + ".png";
}

AIconManager.prototype.getTTIconURL = function(lt_id, tt_id) {
	return this.baseURLSymbols + tt_id + ".png";
}


/**
 * Create icon given its location type id and technology category id.
 * Rules: If tt_id is -2, then group of technologies exist for that location, so return the 'lt_id'_group icon.
 * Otherwise return the 'lt_id'_'tt_id'.png icon. Cache is updated.
 */
AIconManager.prototype.createGIcon = function(lt_id, tt_id) {
	imageName = "";
	if(tt_id == -2) {
		imageName = "lt_" + lt_id + "_group.png";
	} else {
		imageName = lt_id + "_" + tt_id + ".png";
	}
	iconURL = this.baseURL + imageName;
	var gicon = new GIcon(G_DEFAULT_ICON)
	gicon.image = iconURL;
	gicon.iconSize = GSize(34,36);
	gicon.shadow = null;
	return gicon;
}

/**
 * Try to lookup into cache.
 */
AIconManager.prototype.cacheLookup = function(lt_id, tt_id) {
	if(this.iconCache[lt_id] && this.iconCache[lt_id][tt_id]) {
		return this.iconCache[lt_id][tt_id];
	}
	icon = this.createGIcon(lt_id, tt);
	if(!this.iconCache[lt_id]) this.iconCache[lt_id] = {};
	this.iconCache[lt_id][tt_id] = icon;
	return icon;
}
