/*
 * This file should be loaded only when we need a map
 * 
 * CAREFUL
 *
 * As long as we use Google, we need to project to spherical mercator, and project all our Lat/Long
 * 
 */

// can (but should not) be used by all functions
var _map;

// if this is executed, we have javascript, and thus want to hide the fallback bits
addLoadListener(function () {
        var mapok = map_init();

        // hide the inputs that are automatically filled with the map
        if (document.getElementById('nomap') && mapok)
            {document.getElementById('nomap').style.display='none';}

        //hide the nojs warning
        if (document.getElementById('nojs'))
            {document.getElementById('nojs').style.display='none';}

        // reset the nojs flag
        if (document.getElementById('nojs_in'))
            {document.getElementById('nojs_in').value='0';}

        // add submit check on form
        //      addEvent(document.getElementById('qdsf'), 'submit', qd_submit);

    });


//addLoadListener(map_init);

// if this is executed, we have javascript, and thus want to hide the fallback bits
// must be AFTER map_init
addLoadListener(function (){
	// hide the inputs that are automatically filled with the map
	if (document.getElementById('nojs'))
	    {document.getElementById('nojs').style.display='none';}
	// reset the nojs flag
	if (document.getElementById('nojs_in'))
	    {document.getElementById('nojs_in').value='0';}

	// add submit check on form
	//	addEvent(document.getElementById('qdsf'), 'submit', qd_submit);

    });


/* 
 * this needs to be called onload()  
 *
 * please note that to be able to display the navToolbar as expected (horizontally), it is needed to
 * - add the option theme: css_file
 * - properly set the css file pointed by this option 
 *
 * This tries to be the main entry point to set up a map, It thus
 * deals with the case where we have a EPSG:900913 projection (international page), 
 * hence all the if(document,ggIntlPage)
 *
 * There's a lot of if (cocument.ggintlPage) to handle the interantional page.
 * I think it's better to have all the ifs, because it keeps the logic for both init.
 * 
 */
function map_init()
{
    var divmap = document.getElementById('mapinit');
    if (!divmap) {return false;}


    //first, create the params (bounds, extent...) for the map

    //get initial layout
    var startBounds;
    var ukExtent = google(getUKExt());
    var worldExtent;
    //the std params (projection...) will be set in genMap
    var params = new Object();

    if (document.ggIntlPage)
	{
	    worldExtent = google(getWorldExt());
	    
	    //without this, map would not move to show full popup
	    params.maxExtent = worldExtent;
	    params.maxResolution = 156543.0339;
	    //	    params.numZoomLevel = 15;

	    // without this, the bb would wrap around antimeridian
	    params.restrictedExtent = worldExtent;
	    
	    params.wrapDateLine = true;
	}
    else
	{
	    params.maxExtent=ukExtent;
	    params.restrictedExtent=ukExtent;
	}

    if (existsID('xcoord') && existsID('ycoord') && existsID('x2coord') && existsID('y2coord') )
	{
	    startBounds = google(new OpenLayers.Bounds (document.getElementById('xcoord').value,
							document.getElementById('ycoord').value,
							document.getElementById('x2coord').value,
							document.getElementById('y2coord').value));
	}
    else
	{
	    if (document.ggIntlPage) {startBounds = worldExtent}
	    else {startBounds = ukExtent;}
	}


    // finally, get the map itself
    // change id to kick CSS in
    divmap.id='map';
    _map=genMap('map', params);
    if (!_map) {divmap.id='mapinit';return false;}


    // here we are happy, fine tune.
    

    // it is better to do hide the fallback here, to avoid sync issue
    if (document.getElementById('nojs')){document.getElementById('nojs').style.display='none';}
    
    
    if (document.ggIntlPage)
	{
	    //zoom to max extent is a bit confusing becaause of the restricted extent: 
	    // we see the world 3 times but cannot move
	    _map.zoomTo(1);
	    //_map.addControl(new OpenLayers.Control.MousePosition());
	}
    else
	{
	    _map.zoomToExtent(startBounds);
	    _map.zoomTo(4);
	}

    
    if (document.getElementById('xcoord'))
	{
	    _map.events.register('zoomend', _map, function(e) {updCoord(e, _map)});
	    _map.events.register('moveend', _map, function(e) {updCoord(e, _map)});
	}
    return true;
}

function getMap()
{
    return _map;
}


/*
 * Quick data search bit
 */

/*
 * private vars
 */
var _pop_param = "statusbar=0,menubar=0,toolbar=0,scrollbars=1,resizable=1,width=620,height=350";


// called on map events to update the coordinates
function updCoord (e, map)
{
    var map_extent = fromGoogle(map.getExtent());

    document.getElementById('xcoord').value = map_extent.left.toFixed(5);   //west
    document.getElementById('ycoord').value = map_extent.bottom.toFixed(5); //south
    document.getElementById('x2coord').value= map_extent.right.toFixed(5);  //east
    document.getElementById('y2coord').value= map_extent.top.toFixed(5);    //north
    document.getElementById('rec_sess').value='';
    Event.stop(e);
}

/*
 * This is probably a bit pulled by the hair (which probably does not mean anything in english... Whatever)
 * 
 * All the xwalk bit can be called via xhr, popup, form, and can require a form submit (go button)
 * or just a map update (link 'display on map').
 * 
 * to try to accomodate that, goSubmit either register the fact that:
 * - we want to submit (go button, param 1)
 * - we just update the map (link, param 0)
 *
 * when called with any > 1 param, goSubmit actually submit or update the map, depending of how it has been set.
 * when called with any < 0 param, goSubmit returns the _submit var.
 */
var _submit = 1;
function goSubmit (act)
{
    if (act == 1) {_submit = 1}
    else if (act == 0) {_submit = 0}
    else if (act > 1) {
	if (_submit) {document.getElementById('qdsf').submit();}
	else (updateMap());
    }
    else if (act < 0) {return _submit;}
}


// submit a quick data search
function qd_submit()
{
    var kw = document.getElementById('kw') ? document.getElementById('kw').value : undefined;
    var place = document.getElementById('pname').value;
    var map = exists(document.getElementById('xcoord').value) || existsID ('rec_sess');
    // nothing entered => fail
    if (!exists(kw) && !exists(place) && !map)
	{
	    alert("Please supply a geographic extent and/or a keyword");
	    return false;
	}
    // got a place, but not Xwalked yet, or click on link
    else if ((exists(place) && !map) || (goSubmit(-42) == 0 ))
	{
	    return xwalk(place);
	}
    // all other cases are OK: we already have Xwalked, or we've got a mix of kw and map
    else 
	{
	    document.getElementById('qdsf').action='/cgi-bin/results.cgi';
	    return true;
	}
}

/*
 * we got a place name, we want the coordinates from it
 * We try first with an xhr, then fallback on a popup
 */

function xwalk (place)
{

  var xwalk_url = '/cgi-bin/xwalk.cgi';
  var xhr = getXhr();
  if (xhr)
  {
      document.body.style.cursor='wait';
      xhr.onreadystatechange = function () {xhr_done(xhr)};
      xhr.open("GET",xwalk_url+"?pname=" + place + "&ajax=1",true);
      xhr.send(null);
  }
  else
  {
      window.open(xwalk_url + "?pname=" + place, "xwalk", _pop_param);
  }
  return false;
}


 //called when the xmlhttp call is completed, with the result
 function xhr_done (xhr)
 {

	 if (xhr.readyState==4)
	 {
		 document.body.style.cursor = 'default';    
		 // if "OK"
		 if (xhr.status==200)
		 {
			 res = xhr.responseText;

			 // try create json result object
			 var jsonResult = null;
			 
			 if(res != null && res != '' ){
				 
				 try
				  {
					 jsonResult = eval(  "(" + res + ")" );
					 
				  }catch(ignore){ }
			 }

			 if (res == '') {alert ("Sorry, there are no matches for your place name. Please try again.");} 

			 // only one match => we receive 1 followed by the addMeToOlMap params
			 else if (jsonResult != null && jsonResult.results == 1)
			 {

				 setRecSess(jsonResult.recordSessionId, jsonResult.x, jsonResult.y, jsonResult.x2, jsonResult.y2);


				 logme('end of xhr, do submit');
				 goSubmit(42);
			 }
			 else
			 {
				 // popup with text = res
				 var popX = window.open('', "xwalk", _pop_param);
				 popX.document.write(res);
			 }
		 }
		 else
		 {
			 alert("Problem during check. Please retry later.");
		 }
		 document.body.style.cursor='default';
	 }
 }

function setRecSess (rid, x, y, x2, y2)
{
    if (document.getElementById('rec_sess')) 
	{document.getElementById('rec_sess').value = rid;}
    if (document.getElementById('qdsf'))
	{document.getElementById('qdsf').action='/cgi-bin/results.cgi';}

    //this can happen, if we want to handle the 'display on map'
    if (x && y && x2 && y2)
	{
	    document.getElementById('xcoord').value = x;
	    document.getElementById('ycoord').value = y;
	    document.getElementById('x2coord').value = x2;
	    document.getElementById('y2coord').value = y2;
	}

}

function coord_reset ()
{
    var coord = new Array('rec_sess', 'xcoord', 'ycoord', 'x2coord', 'y2coord');
    for (var i in coord)
	{
	    document.getElementById(coord[i]).value = '';
	}
    document.getElementById('qdsf').action='/cgi-bin/xwalk.cgi';    

}


/*
 * update the map from the hidden ccordinate fields, and zoom the map to reflect them.
 */
function updateMap()
{
    if (_map)
	{
	    _map.zoomToExtent(google(new OpenLayers.Bounds(document.getElementById('xcoord').value,
							   document.getElementById('ycoord').value, 
							   document.getElementById('x2coord').value, 
							   document.getElementById('y2coord').value)));
	}
}

/*
 * reset inputs and set the map to its initial extent
 */
function reset_map ()
{
    document.getElementById('xcoord').value = '';
    document.getElementById('ycoord').value = '';
    document.getElementById('x2coord').value = '';
    document.getElementById('y2coord').value = '';
    if (document.getElementById('map')) {document.getElementById('map').innerHTML=''; document.getElementById('map').id='mapinit'}
    map_init();
    return false;
}

/*
 * End of quick data search
 */

/*
 * compare extent bit
 */

//needs to be global
var markers;

//zoom to the marker markers[marker]
function zoomToMarker (marker)
{
    _map.zoomToExtent(markers[marker].bounds);
}

//center to the marker markers[marker]
function centerToMarker (marker)
{
    _map.setCenter(markers[marker].lonlat, 13);
}



/*
 * End of compare extent
 */


/*
 * international bit
 */
var portals = new Array(); 
function initPortals()
{
  // If map has not been loaded, there is nothing to do.
  if (! _map) {return false;}

  // create the general objects
  var markers = new OpenLayers.Layer.Markers("portalsPopups");
  var boxes = new OpenLayers.Layer.Boxes("portalsBoxes");
  _map.addLayers([boxes,markers]);

  var icon =  new OpenLayers.Icon('/img/pin.png', new OpenLayers.Size(18,27));

  //for each elem in portal create the marker
  for (var i in portals)
    {
       var p = portals[i];

       var pos = google(new OpenLayers.LonLat(p.lon, p.lat));
       var cloudFeature = new OpenLayers.Feature(markers, pos);
       cloudFeature.data.icon = icon.clone();
       cloudFeature.data.popupContentHTML = getDescr(i);
       cloudFeature.popupClass = OpenLayers.Popup.FramedCloud;
       var marker = cloudFeature.createMarker();

       //to be able to access the portali id and stay in the Feature context, this is the easiest solution:
       cloudFeature.gg_ppid = i;
       marker.events.register("mousedown", cloudFeature, getPopup);
       marker.setOpacity(0.7);
       markers.addMarker(marker);
       p.marker = marker;
      }
}


/*
 * get the portal's popup on clickdown
 * param: event
 * called on a Feature context, with this.gg_pid set to the portal id
 */
function getPopup(evt)
{ 
    // close all bbs
    _map.getLayersByName('portalsBoxes')[0].clearMarkers();
    
    //then close all popups (can't just clear everything, as it would remove the pins)
    var popups=_map.getLayersByName('portalsPopups')[0].map.popups;
    while (popups.length > 0) { closePopup(); }

    // create our popup
    this.popupClass = OpenLayers.Popup.FramedCloud;

    // as feature.create Popup does not allow to set a callback, I need to do it myself
    this.popup = this.createPopup(true, closePopup);
    //        this.popup.addCloseBox(closePopup);
    _map.getLayersByName('portalsPopups')[0].map.addPopup(this.popup);
    this.popup.show();
    

    // then set boxes
    //extent of everything to be shown
    var showbound = new OpenLayers.Bounds();
    showbound.extend(this.marker.lonlat);

    //get the popup bb(s)
    var boxes = _map.getLayersByName('portalsBoxes')[0];
    var p = portals[this.gg_ppid];
    for (var i in p.bb)
      {
	  var bbounds = new OpenLayers.Bounds(p.bb[i][0], p.bb[i][1], p.bb[i][2], p.bb[i][3]);
	  showbound.extend(bbounds);
	  boxes.addMarker(new OpenLayers.Marker.Box(google(bbounds)), 'red', 1);
      }

    OpenLayers.Event.stop(evt);
}


/*
 * called from a popup
 * it removes all BB and closes the 1st popup on the map
 * as there is only one popup at a time, no need to get it referenced
 */
function closePopup(e)
{
    var popup = _map.getLayersByName('portalsPopups')[0].map.popups[0]
    popup.hide();
    _map.removePopup(popup); // not destroyed, becouse created only once
    if (e) {OpenLayers.Event.stop(e);}

    // close all bbs
    // a bit redondant if called from getPopup, but needs to be here in case it is called via callback
    _map.getLayersByName('portalsBoxes')[0].clearMarkers();
}

/*
 * get decription for portal, embeded in a div with a set width
 */
function getDescr(i)
{
    return "<div class='innerPopup'><h1>" + portals[i].title + "</h1>" + portals[i].descr + "<p><a href='" + portals[i].url + "' onclick='return newwin(this)'>Go to portal</a></p></div>";
}

/*
 * end of international bit
 */
