//
// OSM Shop Nodes Javascript
//
// This file Copyright 2010-2011 Andrew M. Bishop
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//


//==================================================//
// Customise this for specific selector information //
//==================================================//

var selector={selecturl: "shop.txt"};


//================================================//
// Customise this for specific filter information //
//================================================//

var filters=[ {number: 1, checkbox: {prepare: limitToMapPrepare, check: limitToMapCheck}},
              {number: 2, autolist: {any: true, name: "shop", singular: "Shop Type", plural: "Shop Types"}} ];

// The "limit to map" filter

function limitToMapPrepare()
{
 this.mapbounds=map.getExtent().clone();
 this.mapbounds.transform(epsg900913,epsg4326);
}

function limitToMapCheck(datum)
{
 if(!this.doc_checkbox.checked)
    return(true);

 if(datum.lon<this.mapbounds.left)   return(false);
 if(datum.lat<this.mapbounds.bottom) return(false);
 if(datum.lon>this.mapbounds.right)  return(false);
 if(datum.lat>this.mapbounds.top)    return(false);

 return(true);
}

function limitToMapMoved()
{
 if(!filters[0].doc_checkbox.checked)
    return;

 selectFromFilterList();
}

function limitToMapEnable()
{
 var doc_checkbox=document.getElementById("filter1_checkbox");

 doc_checkbox.checked=true;
}


//================================================//
// Customise this for specific sorter information //
//================================================//

var sorters=[ {number: 1, name: "ID",            sort: sortByID},
              {number: 2, name: "Name",          sort: sortByName},
              {number: 3, name: "Shop Type",     sort: sortByShop} ];

// Sort functions

function sortByID(data1,data2)
{
 if(Number(data1.id) < Number(data2.id))
    return(-1);
 else if(Number(data1.id) > Number(data2.id))
    return(1);
 else
    return(0);
}

function sortByName(data1,data2)
{
 if(data1.name < data2.name)
    return(-1);
 else if(data1.name > data2.name)
    return(1);
 else
    return(sortByID(data1,data2));
}

function sortByShop(data1,data2)
{
 if(data1.shop < data2.shop)
    return(-1);
 else if(data1.shop > data2.shop)
    return(1);
 else
    return(sortByName(data1,data2));
}


//================================================//
// Customise this for specific result information //
//================================================//

var results={name: "name", singular: "Shop node", plural: "Shop nodes",
             clear: clearResults, update: updateResults, select: selectResult};


//
// Callback for clearing the results list.
//

function clearResults()
{
 var results_info=document.getElementById("results_info");

 results_info.innerHTML = "";

 layerVectors.destroyFeatures();

 results.features=[];
}


//
// Callback for updating the results list.
//

function updateResults()
{
 // Draw markers

 layerVectors.destroyFeatures();

 results.features=[];

 if(results.list.length>400)
    {
     var results_info=document.getElementById("results_info");

     results_info.innerHTML = "Too many results to display".bold();
    }
 else if(results.list.length>0)
   {
    for(var index=0;index<results.list.length;index++)
      {
       var lon=results.list[index].lon;
       var lat=results.list[index].lat;

       var lonlat= new OpenLayers.LonLat(lon,lat).transform(epsg4326,epsg900913);

       var point = new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);

       var feature = new OpenLayers.Feature.Vector(point,{},
                                                   new OpenLayers.Style({},{stroke: false,
                                                                            pointRadius: 4, fillColor: "#FF0000",
                                                                            label: results.list[index].name,
                                                                            labelAlign: "lt",
                                                                            cursor: "pointer"}));

       feature.index=index;

       results.features[index]=feature;
      }

    layerVectors.addFeatures(results.features);

    layerVectors.events.register("featureselected",layerVectors,clickMarker);
   }

 // Highlight marker

 if(results.list.length>0)
   {
    var lon=results.list[0].lon;
    var lat=results.list[0].lat;

    var lonlat= new OpenLayers.LonLat(lon,lat).transform(epsg4326,epsg900913);

    var point = new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);

    var feature = new OpenLayers.Feature.Vector(point,{},
                                                new OpenLayers.Style({},{stroke: true,
                                                                         pointRadius: 4, fillColor: "#FF0000",
                                                                         strokeWidth: 3, strokeColor: "#FFFF00",
                                                                         display: "none"}));

    feature.index="highlight";

    results.features.highlight=feature;

    layerVectors.addFeatures([feature]);
   }
}


//
// Click on a marker
//

function clickMarker(event)
{
 var index=event.feature.index;

 if(index=="highlight")
    return;

 results.doc_list.options[index].selected=true;

 selectResult(index);
}


//
// Select a result (click on list or click on map)
//

var display_optional_tags=["description","note","source","wikipedia","url"];

function selectResult(index)
{
 if(index==-1)
   {
    results.doc_info.innerHTML="";

    if(results.features!=undefined && results.features.highlight!=undefined)
      {
       results.features.highlight.style.display="none";

       layerVectors.drawFeature(results.features.highlight);
      }
   }
 else
   {
    var lon=results.list[index].lon;
    var lat=results.list[index].lat;

    var lonlat= new OpenLayers.LonLat(lon,lat).transform(epsg4326,map.getProjectionObject());

    results.features.highlight.move(lonlat);
    results.features.highlight.style.display="";

    layerVectors.drawFeature(results.features.highlight);

    // Update the result information in the main panel.

    var html="";

    html = html + "id = " + results.list[index].id;
    html = html + "<br>";
    html = html + "shop = " + results.list[index].shop;
    html = html + "<br>";
    html = html + "name = " + results.list[index].name;

    for(var t=0;t<display_optional_tags.length;t++)
      {
       var tag=display_optional_tags[t];

       if(results.list[index][tag] != undefined && results.list[index][tag] != "")
         {
          html = html + "<br>";
          html = html + tag + " = " + results.list[index][tag];
         }
      }

    html = html + "<p style=\"margin-bottom: 0px\">";
    html = html + "Map: <a href='#' onclick='zoomTo(\"" + index + "\");return false'>Zoom to node</a>";

    html = html + "<br>";
    html = html + "Node: <a target='potlatch' href='http://www.openstreetmap.org/edit?lat=" + results.list[index].lat + ";lon=" + results.list[index].lon + "'>Edit in Potlatch</a>";

    html = html + "<br>";
    html = html + "Route: <a target='routino' href='../routino/customrouter.cgi?lat2=" + results.list[index].lat + ";lon2=" + results.list[index].lon + "'>Calculate a route</a>";

    results.doc_info.innerHTML=html;
   }
}


//
// Map configuration
//

var map;
var layerMap=[], layerVectors;
var epsg4326, epsg900913;


// 
// Initialise the 'map' object
//

function map_init(lat,lon,zoom)
{
 // Map properties (North/South and East/West limits and zoom in/out limits) are now in mapprops.js
 // Map URLs are now in mapprops.js

 //
 // Create the map
 //

 epsg4326=new OpenLayers.Projection("EPSG:4326");
 epsg900913=new OpenLayers.Projection("EPSG:900913");

 map = new OpenLayers.Map ("map",
                           {
                            controls:[
                                      new OpenLayers.Control.Navigation(),
                                      new OpenLayers.Control.PanZoomBar(),
                                      new OpenLayers.Control.ScaleLine(),
                                      new OpenLayers.Control.LayerSwitcher()
                                      ],

                            projection: epsg900913,
                            displayProjection: epsg4326,

                            minZoomLevel: mapprops.zoomout,
                            numZoomLevels: mapprops.zoomin-mapprops.zoomout+1,
                            maxResolution: 156543.0339 / Math.pow(2,mapprops.zoomout),

                            maxExtent:        new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
                            restrictedExtent: new OpenLayers.Bounds(mapprops.westedge,mapprops.southedge,mapprops.eastedge,mapprops.northedge).transform(epsg4326,epsg900913),

                            units: "m"
                           });

 // Add map tile layers

 for(var l=0;l < mapprops.mapdata.length;l++)
   {
    layerMap[l] = new OpenLayers.Layer.TMS(mapprops.mapdata[l].label,
                                           mapprops.mapdata[l].baseurl,
                                           {
                                            emptyUrl: mapprops.mapdata[l].errorurl,
                                            type: 'png',
                                            getURL: limitedUrl,
                                            displayOutsideMaxExtent: true,
                                            buffer: 1
                                           });
    map.addLayer(layerMap[l]);
   }

 // Get a URL for the tile; limited to map restricted extent.

 function limitedUrl(bounds)
 {
  var z = map.getZoom() + map.minZoomLevel;

  if (z>=7 && (bounds.right  < map.restrictedExtent.left ||
               bounds.left   > map.restrictedExtent.right ||
               bounds.top    < map.restrictedExtent.bottom ||
               bounds.bottom > map.restrictedExtent.top))
     return this.emptyUrl;

  var res = map.getResolution();
  var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
  var limit = Math.pow(2, z);

  if (y < 0 || y >= limit)
    return this.emptyUrl;

  var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));

  x = ((x % limit) + limit) % limit;
  return this.url + z + "/" + x + "/" + y + "." + this.type;
 }

 // Add a marker layer

 layerVectors = new OpenLayers.Layer.Vector("Markers");
 map.addLayer(layerVectors);

 var select = new OpenLayers.Control.SelectFeature(layerVectors);

 map.addControl(select);
 select.activate();

 // Set the map centre to the limited range specified

 map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true));
 map.maxResolution = map.getResolution();

 // Move the map

 if(lon != 'lon' && lat != 'lat' && zoom != 'zoom')
   {
    if(lon<mapprops.westedge) lon=mapprops.westedge;
    if(lon>mapprops.eastedge) lon=mapprops.eastedge;

    if(lat<mapprops.southedge) lat=mapprops.southedge;
    if(lat>mapprops.northedge) lat=mapprops.northedge;

    if(zoom<mapprops.zoomout) zoom=mapprops.zoomout;
    if(zoom>mapprops.zoomin)  zoom=mapprops.zoomin;

    var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,map.getProjectionObject());

    map.moveTo(lonlat,zoom-map.minZoomLevel);

    limitToMapEnable();
   }

 map.events.register("moveend", map, mapMoved);
}


//
// Map has moved
//

function mapMoved()
{
 var centre = map.getCenter().clone();

 var lonlat = centre.transform(map.getProjectionObject(),epsg4326);

 var zoom = this.getZoom() + map.minZoomLevel;

 var custom_url=document.getElementById("custom_url");

 var args="lat=" + lonlat.lat + ";lon=" + lonlat.lon + ";zoom=" + zoom;

 var url="custom.cgi?" + args;

 custom_url.href=url;

 var links=document.getElementById('links');

 if(links.hasChildNodes())
   {
    var child=links.firstChild;
    
    do
      {
       if(child.firstChild)
          if(child.firstChild.tagName=='A' || child.firstChild.tagName=='a')
            {
             var orig_url=child.firstChild.href.slice(0,child.firstChild.href.lastIndexOf("/")+1);
             child.firstChild.href=orig_url+url;
            }
      }
    while(child=child.nextSibling);
   }

 limitToMapMoved();
}


//
// Zoom to a specific location
//

function zoomTo(index)
{
 var lon=results.list[index].lon;
 var lat=results.list[index].lat;

 var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,map.getProjectionObject());

 map.moveTo(lonlat,map.numZoomLevels-2);
}

