/* Common JS functions library for wolpy. Using Jquery */

/**
* jQuery DOM ready function 
*/
$(function() {
 	markersSmall = []; // Array of small markers in beenmap
	markersBig = []; // Array of big markets in benmap
	ewindowsSmall = []; // Array of small map markers tooltips
	ewindowsBig = []; // Array of big map markers tooltips
	placeStats = "";
	
	/**
	* Clean login form in the header
	*/
	$("form#login :text, form#login :password").click(function(){
		$(this).val("");
    });
	
	/**
	* Clone DOM elements to add more elements to the list
	* @return false
	*/ 	
	$("p.more a").click(function(){
		var p = $(this).parent().prev();		
		var count = p.attr("id");
		var count = count.split("[");		
		var countf = count[1].split("]");		 

		np = p.clone(true).insertAfter(p).css("opacity", 0.0).fadeTo("normal", 1.0);				
		var idName = np.attr("id");
		idName = idName.split("[");
		idNamef = idName[1].split("]");
		idNamef[0] = parseInt(idNamef[0]) + 1;
		np.attr("id", idName[0] + "[" + idNamef[0] + "]");
		np.find("label").each(function(i){
			var forattr = $(this).attr("for");			
			forattr = forattr.split("[");
			forattrf = forattr[1].split("]");
			forattrf[0] = parseInt(forattrf[0]) + 1;
			$(this).attr("for", forattr[0] + "[" + forattrf[0] + "]");	
			$(this).find("span").html(forattrf[0]);	
		});		
		np.find(":input").each(function(i){
			var idattr = $(this).attr("id");			
			idattr = idattr.split("[");
			idattrf = idattr[1].split("]");
			idattrf[0] = parseInt(idattrf[0]) + 1;
			$(this).attr("id", idattr[0] + "[" + idattrf[0] + "]");	
			$(this).attr("name", idattr[0] + "[" + idattrf[0] + "]");
		});
		np.find(":text").val("");
		if (np.find(":text").attr("id").indexOf("url") >= 0)
			np.find(":text").val("http://");
		$(this)[0].focus();			
		return false;		
    }); 

	/**
	* Give focus to any element with class="focus"
	*/ 
	$(".hasFocus").focus();	
	
	/**
	* Avoid user search to be send with an empty search box
	*/
	$("#usersearch :submit").click(function(){ 
		if ($("#usersearch :text").val() == "")
			return false;
	});
	
	/**
	* Avoid places search to be send with an empty search box
	*/
	$("#search :submit").click(function(){ 
		if ($("#search :text").val() == "")
			return false;
	});	
});

/**
* Create map and event listeners for change icons depending on zoom level.
*/
function createMap(divId, lat, lng, z) {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById(divId));
		map.addControl(new GSmallZoomControl());					
		map.setCenter(new GLatLng(lat, lng), z);    
		
		GEvent.addListener(map, "zoomend", function() {
			markersZoom();
		});
	}
}

/**
* Create place map
*/
function createPlaceMap(lat, lng, z) {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GSmallZoomControl());					
		map.setCenter(new GLatLng(lat, lng), z);  
		map.addControl(new GMapTypeControl());
    var place = new GLatLng(lat, lng);
    map.addOverlay(new GMarker(place));
	}
}

/**
* Create user place map
*/
function createUserPlaceMap(lat, lng, z) {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GSmallZoomControl());					
		map.setCenter(new GLatLng(18, 0), z);  

        var place = new GLatLng(lat, lng);
        
		var icon = new GIcon();
		icon.image = "/img/been4.png";
		icon.iconSize = new GSize(5, 5);
		icon.iconAnchor = new GPoint(2, 2);
		icon.infoWindowAnchor = new GPoint(4, -8); 

		map.addOverlay(new GMarker(place, icon));
	}
}

/**
* Loads JSON object with cities and calls createMarker for each place
* @param url {string} url address from which it's going to read the json output
*/
function loadMarkersJSON (url, iconImage, count) {
	if (typeof iconImage == "undefined") {
		iconImage = "/img/been4.png";
	}
	
	if (typeof count == "undefined") {
		count = 0;
	}	
	
	var request = GXmlHttp.create();
	request.open("GET", url, true);
	request.onreadystatechange = function() {
		if (request.readyState == 4) {
			var objJSON = eval('(' + request.responseText + ')');
			if (objJSON.places) {
				for (var i = 0; i < objJSON.places.length; i++) {
					var lat = parseFloat(objJSON.places[i].latitude);
					var lng = parseFloat(objJSON.places[i].longitude);
					var label = objJSON.places[i].name;
					var geonameId = objJSON.places[i].geoid;
					var point = new GLatLng(lat,lng);
					var marker = createMarker(geonameId, point, label, iconImage);
				}
				if (count) {
					$("#usermap a span").html(objJSON.places.length);
				}
			}
		}
	}
	request.send(null);		
}

/**
* Calls Geonames web service and when receive response call a callback function
* @param place {string} A place name for full text search using geonames web service
* @param callback {string} name of the function that will be called back when receive a response from web service
* @param n {int} number of results to fetch from the webservice (optional, 10 by default)
*/
function geonamesRequest(place, callback, n) {
	if (typeof n == "undefined") {
		n = 10;
	}
	var request = 'http://ws.geonames.net/searchJSON?q=' + place  + '&isNameRequired=true&featureClass=P&maxRows=' + n + '&callback=' + callback + '&style=full&username=wolpy';
	aObj = new JSONscriptRequest(request);
	aObj.buildScriptTag();
	aObj.addScriptTag();
}

/**
* Create two markers (small & big) for each point 
* @param point {object} GLatLng object with the point where the marker will appear
* @param label {string} Text that will appear in the tooltip of the marker
*/
function createMarker(geonameId, point, label, iconImage) {
	if (typeof iconImage == "undefined") {
		iconImage = "/img/been4.png";
	}
	var icon = new GIcon();
	icon.image = iconImage;
	icon.iconSize = new GSize(5, 5);
	icon.iconAnchor = new GPoint(2, 2);
	icon.infoWindowAnchor = new GPoint(4, -8); 
	var marker = new GMarker(point, icon);
	marker.geonameId = geonameId;
	var iconb = new GIcon();
	iconb.iconSize = new GSize(20, 34);
	iconb.iconAnchor = new GPoint(10, 34);
	iconb.infoWindowAnchor = new GPoint(12, -8); 	
	iconb.image = "/img/marker-red-big.png";
	var markerb = new GMarker(point, iconb);
	markerb.geonameId = geonameId;
	markersSmall.push(marker);	
	markersBig.push(markerb);
	GEvent.addListener(marker,"click",function(){ top.location = "/places/" + markerb.geonameId + "/"; }); 
	GEvent.addListener(markerb,"click",function(){ top.location = "/places/" + markerb.geonameId +"/"; }); 
	map.addOverlay(marker);   					
	map.addOverlay(markerb);   
	markerb.hide();
	if (label != "") {
		createTooltip(label, marker, markerb, E_STYLE_8, E_STYLE_9);
	}
	markersZoom();
}	

/**
* Checks the zoom level in the map and chose the appropriate markers
*/
function markersZoom() {
	if (map.getZoom() >= 4) {
		for (var i = 0; i < markersBig.length; i++) {
			markersBig[i].show();
			markersSmall[i].hide();							
		}				
	} else if (map.getZoom() < 4) {
		for (var i = 0; i < markersBig.length; i++) {
			markersBig[i].hide();
			markersSmall[i].show();							
		}					
	}
}

/**
* Create a tooltip for each point in the map
*/
function createTooltip(label, marker, markerb, style, styleb) {
	var ewindow = new EWindow(map, style); 
	var ewindowb = new EWindow(map, styleb); 
	ewindowsSmall.push(ewindow);	
	ewindowsBig.push(ewindowb);
	map.addOverlay(ewindow);
	map.addOverlay(ewindowb);
	
	var message = label;	
	GEvent.addListener(marker, "mouseover", function() {
		ewindow.openOnMarker(marker,message);
	});
	GEvent.addListener(markerb, "mouseover", function() {
		ewindowb.openOnMarker(markerb,message);
	});		
	GEvent.addListener(marker, "mouseout", function() {
		ewindow.hide();
	});				
	GEvent.addListener(markerb, "mouseout", function() {
		ewindowb.hide();
	});	
}

/**
* Calls Geonames web service and when receive response call a callback function
* @param geonames {object} JSON object obtained from Geonames web service
* @return p {string} a HTML  list of different options for a city search (after filtering same country and same state/province cities)
*/
function buildOptionsList(geonames) {
	var p = "";
	for (var i = 0; i < geonames.length; i++) {
		var code = geonames[i].countryCode.toLowerCase();
		var repeatedCountry = 0;
		var repeatedAdmin1 = 0;
		for (var j = 0; j < geonames.length; j++) {			
			if ((i != j) && (geonames[i].countryName == geonames[j].countryName) && (geonames[i].name == geonames[j].name))
				repeatedCountry = 1;
		} 		
		if(repeatedCountry == 1) {
			for (var k = 0; k < geonames.length; k++) {			
				if ((i != k) && (geonames[i].adminName1 == geonames[k].adminName1) && (geonames[i].name == geonames[k].name))
					repeatedAdmin1 = 1;
			}
			if (repeatedAdmin1 == 1 && geonames[i].adminName2 != "") {
				var place = geonames[i].name + ", " + geonames[i].adminName2 + ", " + geonames[i].countryName;
			}
			else {		
				var place = geonames[i].name + ", " + geonames[i].adminName1 + ", " + geonames[i].countryName;
			}
		}
		else {
			var place = geonames[i].name + ", " + geonames[i].countryName;
		}
		p += "<li><a href=\"#\" class=\"country " + code + "\" countrycode=\"" + code + "\" geonameId=\"" + geonames[i].geonameId + "\" lat=\"" + geonames[i].lat + "\" lng=\"" + geonames[i].lng + "\" place=\"" + place + "\">" + place + "</a></li>";
	}
	return p;
}

/**
* Cancel action over an item. Hides div.placebox 
* @param geonametId {string} geonamesId that is used as id of the element we want arre working with
* @param action {string} classname of the .visitedplace element we are acting on. Depends on the action we are doing (editing, removing, viewvisitors, reviewing)
*/
function cancelOptions(geonameId, action) {
	$("#" + geonameId).find(".editplacebox").hide();
	$("#" + geonameId).removeClass("editing"); 
}	

/**
* Cancel action over all items. Hides div.placebox 
*/
function cancelOptionsAll() {
	$(".visitedplace").find(".editplacebox").hide();
	$(".visitedplace").removeClass("editing"); 
}	
  
/**
* Deletes a place and its marker, then calls updateBeen to delete it from DB
* @param geonameId {string} Id of the place we want to delete, according to geonames
* @return false
*/
function deletePlace(geonameId) {
	var hasTrips = 1;
	if ($("#" + geonameId + " .tripexcerpt").length > 0)
		hasTrips = confirm("There are trips in this place, are you sure you want to delete it?");
	if (hasTrips) {
		$("#" + geonameId).remove();
		for(i = 0; i < markersSmall.length; i++) {
			if (geonameId == markersSmall[i].geonameId) {
				map.removeOverlay(markersSmall[i]);
				map.removeOverlay(markersBig[i]);
			}
		}
		updateBeen("", geonameId, "delete");
	}
	return false;
}

/**
* Deletes a marker, using its unique id
* @param geonameId {string} Id of the marker we want to delete
*/
function deleteMarker(geonameId) {
	for(i = 0; i < markersSmall.length; i++) {
		if (geonameId == markersSmall[i].geonameId) {		
			map.removeOverlay(markersSmall[i]);
			map.removeOverlay(markersBig[i]);
		}
	}
}

/**
* Clean every marker of the map
*/
function cleanMap() {
	for(i = 0; i < markersSmall.length; i++) {
		map.removeOverlay(markersSmall[i]);
	}
	for(i = 0; i < markersBig.length; i++) {
		map.removeOverlay(markersBig[i]);
	}
}

/**
* Edit a place and its marker, then calls updateBeen to update the DB
* @param geonameId {string} Id of the place we want to edit, according to geonames
* @return false
*/
function editPlace(geonameId) {
	if (!$("#" + geonameId).hasClass("editing")) {
		cancelOptions(geonameId, "editing");
		cancelOptionsAll();
		$("#" + geonameId).addClass("editing");
		$("#" + geonameId).find(".editplacebox").show();
		$("#" + geonameId + " .mean").attr("class", "mean mean5");		

		$("#" + geonameId + ".editing li a").click(function() {
			$(".editing li").show();
			$(this).parent().hide();
			$(".editing .placename").html($(this).attr("place"));
			$(".editing .placename").attr("href", "/places/" + $(this).attr("geonameId"));
			$(".editing .placemeta a").attr("href", "/places/" + $(this).attr("geonameId"));			
			$(".editing .add").attr("href", "/trip/add/" + $(this).attr("geonameId"));
			$(".editing .placename").attr("class", "placename country " + $(this).attr("countrycode"));				
			$(".editing h2").attr("countrycode", $(this).attr("countrycode"));

			$(".editing h2 .delete").remove();
			$(".editing h2").append(" <span class=\"delete\"><a onclick=\"deletePlace('" + $(this).attr("geonameId") + "'); return false;\" href=\"#\">Delete</a></span>");
		
			$(".editing .mean p:first").append("<a class=\"edit\" style=\"background-color:#ffffcc\" href=\"#\" onclick=\"editPlace('" + $(this).attr("geonameId") + "'); return false;\">" + $(".editing .edit").html() + "</a>");
			$(".editing .edit:first").remove();
			
			$(".editing .close").remove();
			$(".editing .editplacebox").append("<a class=\"close\" href=\"#\" style=\"margin-top: -14px;\" onclick=\"cancelOptions('" + $(this).attr("geonameId") + "', 'editing'); return false;\">Close</a>");

			var placeStats = getPlaceStats($(this).attr("geonameId"));
			$(".editing .placemeta a").html(placeStats);
	  
			cancelOptions(geonameId, "editing");	
      		$("#" + geonameId + " .mean").removeClass("mean5");
			updateBeen(geonameId, $(this).attr("geonameId"), "edit");	
			deleteMarker(geonameId);
			var newPoint = new GLatLng($(this).attr("lat"), $(this).attr("lng"));
			createMarker($(this).attr("geonameId"), newPoint, $(this).attr("place"));	
			$("#" + geonameId).attr("id", $(this).attr("geonameId"));
			$(this).unbind();
			geonameId = $(this).attr("geonameId");
			return false;
		});	 
	} else {
		cancelOptions(geonameId, "editing");
	}
}

/**
* Calls a PHP script which echoes a json object with stats about a place
* @param geonameId {string} Id of the place, according to geonames webservice
* @return placeStats {string} The number of visitors and the number of reviews in a formatted string
*/
function getPlaceStats(geonameId){
	var statsURL = "/places/" + geonameId + "/stats";
	
	var stats = jQuery.ajax({
		url: statsURL,
		async: false
	}).responseText;
	
	stats = eval('(' + stats + ')');			
	var visitors = stats.visitors;
	var reviews = stats.reviews;		
	if (parseInt(visitors) > 1)
		var visitedBy = "<strong>" + (parseInt(visitors) + 1) + "</strong> visitors"; 
	else 
		var visitedBy = "<strong>1</strong> visitor (you)";

	if (parseInt(reviews) > 0)
		var numReviews = " and <strong>" + reviews + "</strong> reviews"; 
	else 
		var numReviews = "";   

	placeStats = visitedBy + numReviews;	
	return placeStats;
}

/**
* Calls a PHP script which updates the visited places of the user in the DB
* @param geonameId {string} Id of the place to update, according to geonames webservice
* @param action {string: add | delete} Action that we are doing.
* @return false
*/
function updateBeen(old_geonameId, geonameId, action){
	if(action == 'add'){
		var url = "/map/add/" + geonameId;
	}	
	if(action == 'delete'){
		var url = "/map/delete/" + geonameId;
	}
	if(action == 'edit'){
		var url = "/map/edit/" + old_geonameId + "/" + geonameId;
	}
	jQuery.ajax({
		data: {
			ajax: 1
		},
		url: url,
		type: 'POST',
		dataType: 'json',
		timeout: 18000,
		success: function(data) {
			if (data.status == 'error') {
				alert("Sorry, an error ocurred when trying to " + action + " this place. Please try again later or contact us if the error persists.");
				$.post("/send-error", { subject: "[Visited Places] Error trying to " + action + " a place", body: nick + " tried to " + action + " the place with Id: " + geonameId + ". Script at: " + url + " returned: " + data.message } );
				return;
			} else if (data.status == 'ok') {
				if($("#beenmap").length) {
					$("#vptit p").remove();
					$("#vptit").append(data.html);
				}
			}
		}
	})	
	return false;
}

/**
* General function to toggle display of an element
*/ 	
function openClose(elem) {
	$(elem).toggle();
}

/**
* General function wrapper to remove an element
*/ 	
function removeElm(elem) {
	$(elem).remove();
}
