var searchID = 0;
var searchCritID = 0;
var searchCriteria = [];
var crumbTimer;
var lastBalloon = -1;
var balloonMarker;
var map;
var myCluster;
var favicon;
var wishicon;
var friendfavicon;
var icon;
var markersByID = [];
var needsToFit = false;
var locatorMarker;

// helper to find elements by a regular expression
function getElementsByRegExpId(p_regexp, p_element, p_tagName) {
	p_element = p_element === undefined ? document : p_element;
	p_tagName = p_tagName === undefined ? '*' : p_tagName;
	var v_return = [];
	var v_inc = 0;
	for(var v_i = 0, v_il = p_element.getElementsByTagName(p_tagName).length; v_i < v_il; v_i++) {
		if(p_element.getElementsByTagName(p_tagName).item(v_i).id && p_element.getElementsByTagName(p_tagName).item(v_i).id.match(p_regexp)) {
			v_return[v_inc] = p_element.getElementsByTagName(p_tagName).item(v_i);
			v_inc++;
		}
	}
	return v_return;
}

function show(what, alignWith)
{
	document.getElementById(what).style.display = 'block';
	//document.getElementById(what).style.left = findLeftPos(document.getElementById(alignWith));
	//document.getElementById(what).style.top = findTopPos(document.getElementById(alignWith));
}

function catSort(x, y)
{
	if (x.count < y.count)
		return 1;
	else if (x.count > y.count)
		return -1;
	else
		if (x.name == y.name)
			return 0;
		else if (x.name < y.name)
			return -1;
		else
			return 1;
}

function buildCategoryLinks()
{
	var sortedCats = [];
	for (var i in allcats)
	{
		if ((i * 1 == i) && catcounts[i] > 0) // need (i * 1 == i) to prevent garbage >:/
		{
			var cat = new Object();
			cat.id = i;
			cat.count = catcounts[i];
			cat.name = allcats[i];
			sortedCats.push(cat);
		}
	}

	var linkItems = [];
	var selectedCat = $('#category').val();

	if (selectedCat != '') {
		if (sortedCats.length == 0) {
			sortedCats.push({
				'id': selectedCat,
				'count': 0,
				'name': allcats[selectedCat]
			});
		}
		
		linkItems.push('<li><a href="javascript:void(0);" onclick="document.getElementById(\'category\').value=\'\'; updateMarkers(false, true);">&laquo; Show all</a></li>');
	}
	
	sortedCats.sort(catSort);
	for (i = 0; i < sortedCats.length; i++)
	{
		var link = new StringBuffer().append("<li><a href='javascript:void(0);' ");
		if (selectedCat == sortedCats[i].id)
		{
			link.append("onclick='document.getElementById(\"category\").value=\"\"; updateMarkers(false, true);' onmouseover='javascript:document.getElementById(\"validimg\").src = \"/media/invalid.gif\";' ").append(
				"onmouseout='javascript:document.getElementById(\"validimg\").src = \"/media/valid.gif\";'><b>").append(
				"<img src='/media/valid.gif' border='0' id='validimg' width='12' height='12' /> only ").append(sortedCats[i].name).append("</b></a></li>");
		}
		else
		{
			link.append("onclick='document.getElementById(\"category\").value = ").append(sortedCats[i].id).append("; updateMarkers(false, true); ").append(
				"'>").append(
				sortedCats[i].count + " " + sortedCats[i].name + "</a></li>");
		}
		
		linkItems.push(link.toString());
	}
	
	if (linkItems.length == 0)
	{
		// well shucks
		$('#catLinksOuter').slideUp();
	}
	else
	{
		var html = new StringBuffer();
		var showByDefault = 5;
		
		for (var j = 0; j < showByDefault && j < linkItems.length; j++) {
		    html.append(linkItems[j]);
		}
		
		if (linkItems.length > showByDefault) {
		    html.append("<li><a href='javascript:void(0);'><b>more</b>  <img src=\"/templates/front/default/images/arrow_down.png\" border=\"0\" /></a><ul style='z-index: 900'>");
		    for (var j = showByDefault; j < linkItems.length; j++)
		    {
			    html.append(linkItems[j]);
		    }
		    html.append("</ul></li>");
		}

	    $('#catLinks').html(html.toString());
		$('#catLinksOuter').slideDown();
	
        $('#catLinks.jsddm > li').bind('mouseover', jsddm_open)
        $('#catLinks.jsddm > li').bind('mouseout',  jsddm_timer);
	}
}

function updatePositionFields()
{
    var bounds = map.getBounds();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();

    document.getElementById('nefield').value = northEast.lng() + ',' + northEast.lat();
    document.getElementById('swfield').value = southWest.lng() + ',' + southWest.lat();
	var currentCenter = bounds.getCenter().lat() + "," + bounds.getCenter().lng();
    document.getElementById('centerfield').value = currentCenter;
    document.getElementById('zoomfield').value = map.getZoom();
}

function getBounds(shouldFit)
{
    updatePositionFields();

    updateMarkers(shouldFit, true);
}

function setBounds()
{
    var ne = document.getElementById('nefield').value.split(',');
    var sw = document.getElementById('swfield').value.split(',');
    
    var newBounds = new GLatLngBounds(new GLatLng(ne[1], ne[0]), new GLatLng(sw[1], sw[0]));
    var newCenter = newBounds.getCenter();
    var newZoom = document.getElementById('zoomfield').value = map.getZoom();
    
    map.setCenter(newCenter, newZoom);
    
    updateMarkers(false, false);
}

function disableEventCatch()
{
    GEvent.clearListeners(map, "moveend");
    GEvent.clearListeners(map, "move");
}

function enableEventCatch()
{
    GEvent.addListener(map, "moveend", function() {
    	getBounds(false);
    });
}

function createLocatorMarker() {
	var locatorIcon = new GIcon(G_DEFAULT_ICON, "/media/animatedblip.gif");
	locatorIcon.iconSize = new GSize(40, 40);
	locatorIcon.iconAnchor = new GPoint(19, 20);
	locatorIcon.shadowSize = new GSize(0, 0);
	locatorMarker = new GMarker(new GLatLng(0, 0), 
	    {
	        icon: locatorIcon,
	        zIndexProcess: function(marker) {
	            return 10e9;
	        }
	    });
	map.addOverlay(locatorMarker);
	locatorMarker.hide();
}

function showLocatorMarkerFor(forID) {
	var latlng = markersByID[forID].getLatLng();
	showLocatorMarker(latlng);
}

function showLocatorMarker(latlng) {
	locatorMarker.setLatLng(latlng);
	locatorMarker.show();
}

function hideLocatorMarker() {
	locatorMarker.hide();
}

function createCoolMarker(guideItem) {
    var myIcon;
    if (guideItem.fv == "1")
          myIcon = favicon;
    else if (guideItem.iw == "1")
    	  myIcon = wishicon;
    else if (guideItem.ff == "1")
          myIcon = friendfavicon;
    else
          myIcon = icon;

    var marker = new GMarker(new GLatLng(guideItem.lt, guideItem.lg), myIcon);
    GEvent.addListener(marker, "click", function() {
        disableEventCatch(); // so markers don't get reloaded by accident
        lastBalloon = guideItem.id;
        balloonMarker = marker;
        var url = "/ajax_exec/getItemDescriptions.php?width=450&max_len=200&ids=" + guideItem.id;
        if (userid != -1)
        	url += "&userid=" + myuserid;
    	if (ignoreFriendFavs)
    		url += '&ignoreFriendFavs=true';
    	// add timestamp to prevent caching of ajax response
    	url += '&timestamp=' + new Date().getTime();
    	url += '&closeButton=true';
        GDownloadUrl(url, setBalloonContents);
    });
    marker.isfav = (guideItem.fv == "1");

    return marker;
}

function setBalloonContents(data)
{
    balloonMarker.openInfoWindowHtml(data, { maxWidth: 450 });
	setTimeout('enableEventCatch()', 900);
}

function createRequestURL(bool)
{
    if (bool)
          document.getElementById('lastCaller').value = 'form';
    else
          document.getElementById('lastCaller').value = 'move';

    // formulate some criteria
    var options = '';
    var $globsearch = $("#globsearch");
    var cat = document.getElementById("category");
    var favsonly = document.getElementById("searchin");
    var friendfavsonly = document.getElementById("friendfavsonly");
    var newitemsonly = document.getElementById("newitemsonly");
	var selectedFolders = document.getElementById("selectedFolders");

    var globsearchOld = document.getElementById("globsearchOld");
    var catOld = document.getElementById("categoryOld");
    var favsonlyOld = document.getElementById("favsonlyOld");
    var friendFavsonlyOld = document.getElementById("friendFavsonlyOld");
    var newItemsOnlyOld = document.getElementById("newItemsOnlyOld");
	var ignoreBounds = bool; //($globsearch.val() != globsearchOld.value);
	var selectedFoldersOld = document.getElementById("selectedFoldersOld");

    if (bool) {
		if ($globsearch.val() == globsearchOld.value &&
			cat.value == catOld.value &&
			favsonly.value == favsonlyOld.value &&
			friendfavsonly.value == friendFavsonlyOld.value &&
			newitemsonly.value == newItemsOnlyOld.value &&
			selectedFolders.value == selectedFoldersOld.value) {
				
			return false;
		}
		//else {
			//if (globsearchOld.value == "") {
			//	changeOrder('relevance', false);
			//}
			
		//}
	}
	globsearchOld.value = $globsearch.val();
	catOld.value = cat.value;
	favsonlyOld.value = favsonly.value;
	friendFavsonlyOld.value = friendfavsonly.value;
	newItemsOnlyOld.value = newitemsonly.value;
	selectedFoldersOld.value = selectedFolders.value;
    
    var fo = (favsonly.value == "favs" || favsonly.value == "all" ? "true" : "");
    var wo = (favsonly.value == "wish" || favsonly.value == "all" ? "true" : "");
    var folders = "";
    if (favsonly.value != "favs" && favsonly.value != "wish" && favsonly.value != "all" && favsonly.value.length > 0) {
    	folders = favsonly.value;
    }

    options += '&globsearch=';
    options += $globsearch.val();
    options += '&cat=';
    options += cat.value;
    options += '&searchid=';
    options += ++searchID;
    options += '&favsonly=';
    options += fo;
    options += '&wishonly=';
    options += wo;
    options += '&friendfavsonly=';
    options += friendfavsonly.value;
    options += '&newitemsonly=';
    options += newitemsonly.value;
	options += '&ignoreBounds=';
	if (ignoreBounds)
		options += 'true';
	options += '&ignoreFriendFavs=';
	if (ignoreFriendFavs)
		options += 'true';
		
	// find selected folders
	if (folders.length > 0)
	{
		options += '&folders=';
		options += folders;
	}

    // get the pos boxes
    var nefield = document.getElementById("nefield");
    var swfield = document.getElementById("swfield");
    var lastcaller = document.getElementById('lastCaller');

    // construct the url
    var requestURL = '/ajax_exec/geomarkers.php?ne=' + nefield.value;
    requestURL += '&sw=' + swfield.value;
    if (nefield.value == ',' || swfield.value == ',')
        requestURL += '&ignoreBounds=true';
    requestURL += "&sort=" + sort;
    requestURL += '&userid=';
    if (userid != -1)
        requestURL += userid;
    requestURL += '&myuserid=';
    if (myuserid != -1)
        requestURL += myuserid;
    requestURL += options;
    
    return requestURL;
}

function convertJSON(data)
{
    // no data returned? well damn, something really went wrong!
    if (!data)
    {
        // fake the required data
        data.guideItems = [];
        data.locCrumb = [];
        data.cats = [];
        data.favcount = 0;
        data.friendfavcount = 0;
    }
    else
    {
        /*data = JSON.parse(data, function (key, value) {
              var type;
              if (value && typeof value === 'object') {
                    type = value.type;
                    if (typeof type === 'string' && typeof window[type] === 'function') {
                        return new (window[type])(value);
                    }
              }
              return value;
        });*/ eval('data = ' + data); // eval is not very safe, but about 2 times as fast...
    }
    
    return data;
}

function updateMarkers(bool, shouldSaveState)
{
    if (shouldSaveState)
        // save state
        saveState();
        
    var requestURL = createRequestURL(bool);
    
    // if there's no valid url
    if (!requestURL)
        // nothing to do
        return;

    document.getElementById('resultsentries').innerHTML = "<div align='center' style='margin-top: 150px;'><img src='/media/ajax-loader.gif'> Loading...</div>";
    document.getElementById('loadOverlay').style.display = "block";

    //window.prompt("De gebruikte URL:", requestURL + '&debug=true');
    // request the data
    GDownloadUrl(requestURL, function(data) {
    	startProfile();
	    profile("JSON Parse");
    	
        data = convertJSON(data);
        
        putMarkers(data);
        
        // endProfile();
    });
}

function updateDataOnly()
{
    var requestURL = createRequestURL(false);
    
    // if there's no valid url
    if (!requestURL)
        // nothing to do
        return;

    //window.prompt("De gebruikte URL:", requestURL + '&debug=true');
    // request the data
    GDownloadUrl(requestURL, function(data) {
    	startProfile();
	    profile("JSON Parse");
    	
        data = convertJSON(data);
        
        // update array with id's for results tab
        var _gi = data.guideItems;
        var _len = _gi.length;
        allResults = [];
        for (var i = 0; i < _len; ++i) {
              allResults.push(_gi[i].id);
        }
        
        putData(data);
    });
}

var profiling = [];
var profilingLabels = [];
var profIndex = 0;
function startProfile()
{
	profIndex = 0;
	profiling[profIndex++] = new Date();
}
function profile(name)
{
	profiling[profIndex] = new Date();
	profilingLabels[profIndex++] = name;
}
function endProfile()
{
	profiling[profIndex] = new Date();
	var totalTime = profiling[profIndex] - profiling[0];
	var text = "Total time taken: " + totalTime + "ms";
	
	for (var i = 1; i < profIndex; i++)
	{
		var taken = (profiling[i + 1] - profiling[i]);
		text += "\n" + profilingLabels[i] + " took " + taken + "ms (" + (taken / totalTime) * 100 + "%)";
	}
	
	alert(text);
}

function putMarkers(data)
{
	profile("Marker cleaning");
	
    // clear the working image
    document.getElementById('loadOverlay').style.display = "none";

    if (data.searchID != searchID)
    {
          // old search that was not completed on time
          return;
    }
    
    // performance tricks, store some stuff in local vars
    var _cluster = myCluster;
    var _ccm = createCoolMarker;
    var _gi = data.guideItems;
    var _len = _gi.length;
    
    // remove old markers
    _cluster.removeMarkers();
    map.clearOverlays();
    allResults = [];
    
    profile("Marker generation");

    // add all markers to the map
    for (var i=0; i < _len; ++i) {
          var item = _gi[i];
          var marker = _ccm(item);
          _cluster._mapMarkers.push(marker);
          allResults.push(item.id);
          markersByID[item.id] = marker;
    }

    profile("Map refreshing");
    
    // refresh the markers
    createLocatorMarker();
    _cluster.refresh(true);
    
    profile("Map fitting");
    
    // auto-fit
    if (data.guideItems.length > 0 &&
          document.getElementById('lastCaller').value == 'form' &&
          (document.getElementById('globsearch').value != '' ||
          document.getElementById('category').value != '' ||
          document.getElementById('searchin').value != '' ||
          document.getElementById('friendfavsonly').value != ''))
    {
        fitMap();
    }
    
    putData(data);
}

function fitMap()
{
      // temporarily remove listener so we can safely fit map
      disableEventCatch();
      myCluster.fitMapToMarkers();
      // add it again
      enableEventCatch();
}

function putData(data)
{
    profile("HTML Updating");

    if (data.guideItems.length == 0) {
    	if (userid == myuserid && data.searchID == 1 && document.getElementById('searchin') == 'favs') {
    		document.getElementById('resultsentries').innerHTML = '						\
    			<div style="margin-top: 100px; padding: 0px 20px; font-size: 14px;">	\
    			<b>Looks like you haven\'t added any spots to your map yet!</b>			\
		        <br /><br />															\
		        You can create your own awesome Sparkx map by adding spots that you love,\
		        have visited or want to go to! This is how:								\
		        																		\
		        <ol>																	\
		            <li><a href="/guide/add" style="color: #D21C5B;">Add your spots</a> in 3 easy steps</li>	\
		            <li><a href="/sparkx" style="color: #D21C5B;">Check your map</a> to see them</li>			\
		            <li><a href="/profile/edit" style="color: #D21C5B;">Pimp your map</a> in the Settings screen</li>	\
		        </ol>																	\
		        																		\
		        So <a href="/guide/add" style="color: #D21C5B;">get started now</a> adding spots!';
		    disableEventCatch();
    	} else {
    		document.getElementById('resultsentries').innerHTML = "<div align='center' style='margin-top: 150px;'>No results found</div>";
    	}
    }

    // first reset category counts
    for (i in catcounts)
    {
        catcounts[i] = 0;
    }

    // update category counts
    for (i in data.cats)
    {
        catcounts[i] = data.cats[i].count;
    }

    // if there's only one marker, and the caller is the form
    if (data.guideItems.length == 1 &&
          document.getElementById('lastCaller').value == 'form')
    {
        // open the popup window right away
        GEvent.trigger(allResults[0], "click");
    }
    
    profile("Category links");
    
    buildCategoryLinks();
    
    profile("Result tabs");
    
    loadPage(0, true);
    
    // put the breadcrumps seperately (because it's likely we moved
    // after getting the markers)
    var bounds = map.getBounds();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();
    var nefield = document.getElementById("nefield");
    var swfield = document.getElementById("swfield");
    
    nefield.value = northEast.lng() + ',' + northEast.lat();
    swfield.value = southWest.lng() + ',' + southWest.lat();// get the pos boxes
    
    updatePositionFields();
    if (document.getElementById('zoomfield').value > 3)
    {
        // construct the url
        var requestURL = '/ajax_exec/getLocationCrumb.php?ne=' + nefield.value;
        requestURL += '&sw=' + swfield.value;

        //window.prompt('', requestURL);
        // request the data
        GDownloadUrl(requestURL, putBreadCrumps);
    }
    else
    {
        // nog niet relevant, geef gewoon "Wereld"
        putBreadCrumps(false);
    }
}

function newSearch() {
	$("#category, #globsearch, #friendfavsonly").val("");
	map.setCenter(new GLatLng(28, 15.1), 1);
}

function putBreadCrumps(data)
{
    // no data returned? well damn, something really went wrong!
    if (!data)
    {
        // fake the required data
        data = [];
    }
    else
    {
        /*data = JSON.parse(data, function (key, value) {
              var type;
              if (value && typeof value === 'object') {
                    type = value.type;
                    if (typeof type === 'string' && typeof window[type] === 'function') {
                        return new (window[type])(value);
                    }
              }
              return value;
        });*/ eval('data = ' + data + ''); // eval is not very safe, but about 2 times as fast...
    }

    //put crumb in page
    if (data.length > 0) {
        $crumbs = $('#navigationCrumbs').empty();
        $crumbs.append("<li><a href='javascript:void(0);' onclick='javascript: newSearch();'>New search &raquo;</a></li>")
        $crumbs.append("<li><a href='javascript:void(0);' onclick='javascript: map.setCenter(new GLatLng(28, 15.1), 1);'>World &raquo;</a></li>");

        for (i = data.length - 1; i >= 0; i--) {
            $crumbs.append("<li><a href=# onclick='javascript: map.setCenter(new GLatLng("+ data[i]['ctGeoCode'] +"),"+data[i]['ctZoom'] + ");'>" + data[i]['ctName'] + (i != 0 ? " &raquo;" : "") + "</a></li>");
        }
        
        $crumbsHolder = $('#breadcrumps');
        if (!$crumbsHolder.is(':visible')) {
            $('#defaultTopPlaces').hide();
            $crumbsHolder.show();
        }
    } else {
        $crumbs = $('#navigationCrumbs').empty();
        $default = $('#defaultTopPlaces');
        $crumbsHolder = $('#breadcrumps');
        
        if (!$default.is(':visible')) {
        	$crumbsHolder.hide();
            $default.show();
        }
    }
}
