var map, projGoogle, projLl;
var layersloaded = 0;

/**
 * Function: initMap
 * Sets up the map, its layers and controls.
 * lat, lon, zoom are the initial map position, provided a permalink has not been used
 */
function initMap(lat, lon, zoom, pois) {
    projGoogle = new OpenLayers.Projection("EPSG:900913");
    projLl = new OpenLayers.Projection("EPSG:4326");
    
    map = new OpenLayers.Map("map", {
        maxExtent: new OpenLayers.Bounds(-20037508,-20037508,20037508,20037508), //
        numZoomLevels: 19,        // this block required for
        maxResolution: 156543,    // overlays to show
        units: 'm',               //
        controls: [],
        projection: projGoogle,
        displayProjection: projLl
    });
    
    // Default baselayers
    map.addLayer(new OpenLayers.Layer.OSM.Mapnik("Normal map"));
    map.addLayer(new OpenLayers.Layer.OSM.CycleMap("Cycle map"));
    map.addLayer(new OpenLayers.Layer.OSM.PublicTransportMap("Public transport map"));

    if(pois) {
      initPoiLayers(); // (handles map.addLayer, since async)
      map.addLayers(initExternalLayers());
      initFeatureSelect();
    }
    
    map.addControl(new OpenLayers.Control.OPLSLayerSwitcher({
		divs: ["layer_selector_map", "layer_selector_green", "layer_selector_local"],
		conditions: ["isBaseLayer", "isGreenLayer", "isLocalLayer"],
        defaultCondition: 2
	}));
    map.addControl(new OpenLayers.Control.Navigation());
    map.addControl(new OpenLayers.Control.PanZoomBar());
    map.addControl(new OpenLayers.Control.Permalink("permalink"));
    map.addControl(new OpenLayers.Control.ArgParser());

    if(!map.getCenter()) {
        map.setCenter(new OpenLayers.LonLat(lat, lon).transform(projLl, projGoogle), zoom);
    }
    
    return map;
}

/****************************
 * Layer addition functions *
 ****************************/

/**
 * Function: initPoiLayers
 * Requests server for available custom POI layers, then proceeds to add them to the map.
 *
 * Returns: nothing (most of the work is async depending on retrieval of layers)
 */
function initPoiLayers() {
    var request = OpenLayers.Request.GET({
        url: '/layer/categories',
        success: function(request) {
            var json = new OpenLayers.Format.JSON();
            var poiLayers = json.read(request.responseText);
        
            if(poiLayers && (poiLayers = poiLayers.features)) {
                var style = new OpenLayers.StyleMap({
                    "default": new OpenLayers.Style({
                        externalGraphic: '${externalgraphic}',
                        graphicWidth: '${externalgraphicwidth}',
                        graphicHeight: '${externalgraphicheight}'
                    })
                });
                for(var l = 0, len=poiLayers.length; l < len; l++) {
                    var name = poiLayers[l].properties.name;
                    var id = poiLayers[l].id;
                    initPoiLayer(name, id, style);
                }
            }
            initFeatureSelect();
        },
        failure: function() {
            initFeatureSelect();
        }
    });
}

/**
 * Function: initPoiLayer
 * Initialises and adds a custom POI layer to the map
 */
function initPoiLayer(name, id, style) {
    var url = '/layer/pois';
    var layer = new OpenLayers.Layer.Vector(name, {
        strategies: [new OpenLayers.Strategy.BBOX({preload: false})],
        protocol: new OpenLayers.Protocol.HTTP({
            url: url,
            format: new OpenLayers.Format.GML(),
            params: {queryable: 'categoryid', categoryid: id, format: 'GML'}
        }),
        visibility: false,
        projection: projLl,
        descriptionFormat: '<h2>${name}</h2>${description}',
        styleMap: style,
        isGreenLayer: true
    });
    map.addLayer(layer);
    
}

function initExternalLayers() {
    var fix = new OpenLayers.Layer.Vector("<a href=\"http://www.fixmystreet.com\" title=\"Reports of local problems, you can submit your own!\" target=\"_blank\">Fix My Street</a> issues", {
        strategies: [new OpenLayers.Strategy.Fixed({preload: false})],
        protocol: new OpenLayers.Protocol.HTTP({
            url: "/feed/fixmystreet",
            format: new OpenLayers.Format.GeoRSS()
        }),
        visibility: false,
        projection: projLl,
        descriptionFormat: '<h2><a href="${link}">${title}</a></h2>${description}',
        style: {externalGraphic: "/pois/alert.png", graphicWidth: 22, graphicHeight: 22}
    });
    
    var planning = new OpenLayers.Layer.Vector("Planning Applications", {
        strategies: [new OpenLayers.Strategy.Fixed({preload: false})],
        protocol: new OpenLayers.Protocol.HTTP({
            url: "/feed/planning",
            format: new OpenLayers.Format.GeoRSS()
        }),
        visibility: false,
        projection: projLl,
        descriptionFormat: '<h2><a href="${link}">${title}</a></h2>${description}',
        style: {externalGraphic: '/pois/planning2.png', graphicHeight: 22, graphicWidth: 22}
    });

    var style = new OpenLayers.Style({externalGraphic: "${img_url}", pointRadius: 30});
    var selectStyle = new OpenLayers.Style({pointRadius: 50});
    var styleMap = new OpenLayers.StyleMap({"default": style, "select": selectStyle});
    
    var geograph = new OpenLayers.Layer.Vector("Geograph Photos", {
        strategies: [new OpenLayers.Strategy.BBOX({ratio: 1})],
        protocol: new OpenLayers.Protocol.HTTP({
            url: "/feed/geograph",
            format: new OpenLayers.Format.KML({extractStyles: true})
        }),
        visibility: false,
        descriptionFormat: '${description}',
        projection: projLl,
        styleMap: styleMap
    });
    
    geograph.events.register("beforefeatureadded", null, function(evt) {
        // I admit, this is a hack, OL is very difficult when it comes to customising KML styles.
        evt.feature.attributes.img_url = evt.feature.style.externalGraphic;
        evt.feature.style = null;
        evt.feature.layer.drawFeature(evt.feature, "default");
        // We now apply same styles as we do to flickr
    });
    
    var flickr = new OpenLayers.Layer.Vector("OPL Sutton Flickr Photos", {
        strategies: [new OpenLayers.Strategy.BBOX()],
        protocol: new OpenLayers.Protocol.HTTP({
            url: "/layer/oplsflickr",
            format: new OpenLayers.Format.GeoJSON()
        }),
        projection: projLl,
        descriptionFormat: '<h2><a href="http://www.flickr.com/photos/oneplanetsutton/${id}">${title}</a></h2><br/><img src="${img_url}" />',
        styleMap: styleMap,
        visibility: false
    });
    
    //return [fix, planning, geograph, flickr];
    return [fix, planning];
}

/**********************************
 * Layer event handling functions *
 **********************************/

/**
 * Function: initFeatureSelect
 * Called by the init function and initPoiLayers functions as the latter is async
 * depending on a server response. We use layerloaded to try and prevent a race condition.
 */
function initFeatureSelect() {
    if(layersloaded == 1) {
        var layers = map.getLayersBy("isVector", true);
        var selectControl = new OpenLayers.Control.SelectFeature(layers);
        map.addControl(selectControl);
        selectControl.activate();
        OpenLayers.Array.filter(layers, function(layer) {
            layer.events.on({
                "featureselected": function(e) {
                    var f = e.feature;
                    f.popup = new OpenLayers.Popup.FramedCloud("pop",
                        f.geometry.getBounds().getCenterLonLat(),
                        null,
                        '<div>'+OpenLayers.Style.createLiteral(layer.descriptionFormat||'', f.data)+'</div>',
			null, true, function() { selectControl.unselectAll(); }
                    );
                    f.popup.minSize = new OpenLayers.Size(250, 100);
                    f.popup.maxSize = new OpenLayers.Size(300, 200);
                    map.addPopup(f.popup);
                },
                "featureunselected": function(e) {
                    e.feature.popup.destroy();
                    e.feature.popup = null;
                }
            });
        });
    }
    layersloaded++;
}

function onOplsflickrSelect(feature) {
    var url = ''+feature.fid;
    var content = '';
    content += '';
    onFeatureSelect(feature, content);
}
