/* Copyright (C) 2008-2011  Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

See the file COPYING for details.
*/

/* main map */

var current_cat = -1;

/* open a category section */
function toggleCategory(item){
    var id = item.id.split('_').pop();
    var old;
    if (current_cat != -1){
        old = document.getElementById('maincategory_' + current_cat);
    } else {
        img = document.getElementById('maincategory_img_' + id);
        if (img.src.split('/').pop() == "minus.png"){
            current_cat = id;
            old = document.getElementById('maincategory_' + id);
        }
    }
    if(old){
        old.style.display = 'None';
        old_img = document.getElementById('maincategory_img_' + current_cat);
        old_img.src = media_path + "icons/plus.png";
    }
    if (id != current_cat){
        current_cat = id;
        document.getElementById('maincategory_' + current_cat).style.display = 'block';
        img = document.getElementById('maincategory_img_' + current_cat);
        img.src = media_path + "icons/minus.png";
    } else {
        current_cat = 0;
    }
}

/* reopen the current opened categories when a redraw occurs */
function reOpenCurrent(){
    if (current_cat && current_cat != -1){
        document.getElementById('maincategory_' + current_cat).style.display = 'block';
        img = document.getElementById('maincategory_img_' + current_cat);
        img.src = media_path + "icons/minus.png";
    }
}

function reCheckCategories(){
    /* recheck categories when a redraw occurs */
    if (!checked_categories){
        return;
    }
    var checked_categories_ids = checked_categories.split('_');
    inputs = window.document.forms["frm_categories"];
    for (var i = 0; i < inputs.length; i++) {
        input = inputs[i];
        cat_id = input.name.split('_').pop();
        if (checked_categories_ids.indexOf(cat_id) != -1){
            input.checked = true;
        }
        if (input.id == 'display_submited' && display_submited == true){
            input.checked = true;
        }
    }
}

/* get available subcategories for a designed category */
function getSubcategories(category_id){
    var ul = document.getElementById('maincategory_'+category_id);
    var subcats = new Array();
    for (i in ul.children){
        var li = ul.children[i];
        if (li.id){
            subcats.push(li.id.split('_').pop());
        }
    }
    return subcats;
}

/* check all the categories if clicked, unckeck if unclick */
function checkAll(item){
    check = false;
    if(item.checked == true){
        check = true;
    }
    id = item.id.split('_').pop();
    var subcats = getSubcategories(id);
    for (i=0;i < subcats.length; i++){
        var checkbox = document.getElementById('category_'+subcats[i]);
        checkbox.checked = check;
    }
}

var map;
var permalink;

/* default size and offset for icon */
var size = new OpenLayers.Size(21, 25);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);

/* define global variable */
var markers = new Array();
var layerMarkers;
var layerVectors;

var simple = false;
var first = true;

var currentPopup;
var currentFeature;
var clicked = false;

/* show a popup */
function showPop(feature) {
    if (currentPopup != null) {
      currentPopup.hide();
    }
    if (feature.popup == null) {
        feature.popup = feature.createPopup();
        map.addPopup(feature.popup);
    } else {
        feature.popup.toggle();
    }
    currentPopup = feature.popup;
    /* hide on click on the cloud */
    currentPopup.groupDiv.onclick = hidePopUp;
    permalink.updateLink();
}

/* check checked categories */
var checked_categories;
var display_submited = false;

function updateCheckedCategories(){
    /* get checked categories */
    inputs = window.document.forms["frm_categories"];
    checked_categories = '';
    display_submited = false;
    for (var i = 0; i < inputs.length; i++) {
        input = inputs[i];
        // 'category_'.length : 9
        if (input.checked
             && input.name.substring(9, 0) == 'category_'){
            id = input.name.substring(9, input.name.length);
            if(checked_categories) checked_categories += '_';
            checked_categories += id;
        }
        if (input.checked && input.name == 'display_submited'){
            display_submited = true;
        }
    }
    permalink.updateLink();
}

/* load marker and route layer from a JSON feature string */
function loadLayersFromJSON(layer_markers, layer_vectors, geo_objects){
    for (var i = 0; i < geo_objects.features.length; i++) {
        var feature = geo_objects.features[i];
        if (feature.geometry.type == 'Point'){
            putMarker(layer_markers, feature);
        } else if (feature.geometry.type == 'LineString') {
            putRoute(layer_vectors, feature);
        }
    }
}

/* zoom to an area */
function zoomToArea(left, top, right, bottom){
    var bounds = new OpenLayers.Bounds(left, bottom, right, top);
    bounds.transform(epsg_display_projection, epsg_projection);
    map.zoomToExtent(bounds, true);
    loadCategories();
}

/* zoom to a desired category */
function zoomToCategory(category_id){
    var sub_cats = getSubcategories(category_id).join('_');
    zoomToSubCategory(sub_cats);
}

/* zoom to desired sub categories */
function zoomToSubCategory(subcategory_ids){
    /* 0 stand for all categories */
    var uri = extra_url + "getGeoObjects/" + subcategory_ids;
    if (display_submited) uri += "/A_S";
    OpenLayers.loadURL(uri, '', this, zoomToCategoryExtent);
}

/* zoom to a selected category from an http response GeoJSON */
function zoomToCategoryExtent(response){
    if (response.responseText.indexOf('no results') != -1) return;
    var fakeLayerVectors = new OpenLayers.Layer.Vector("Fake vector layer");
    var fakeLayerMarkers = new OpenLayers.Layer.Markers('Fake POIs layer');
    var json = new OpenLayers.Format.JSON();
    var geo_objects = json.read(response.responseText);
    /* load every geo object */
    loadLayersFromJSON(fakeLayerMarkers, fakeLayerVectors, geo_objects);
    var bounds = fakeLayerMarkers.getDataExtent();
    if (bounds){
        bounds.extend(fakeLayerVectors.getDataExtent());
    } else {
        bounds = fakeLayerVectors.getDataExtent();
    }
    if(bounds){
        map.zoomToExtent(bounds);
    }
    fakeLayerMarkers.destroy();
    fakeLayerVectors.destroy();
    loadCategories();
}

/* update the categories with an AJAX request */
function loadCategories(){
    var current_extent = map.getExtent().transform(map.getProjectionObject(),
                                                   epsg_display_projection);
    current_extent = current_extent.toArray().join('_')
    current_extent = current_extent.replace(/\./g, 'D');
    current_extent = current_extent.replace(/-/g, 'M');
    var uri = extra_url + "getAvailableCategories/" + current_extent;
    if (display_submited) uri += "/A_S";
    OpenLayers.loadURL(uri, '', this, updateCategories);
}

function updateCategories(response){
    if (response.responseText.indexOf('no results') != -1) {
        return;
    }
    document.getElementById('categories').innerHTML = response.responseText;
    reCheckCategories();
    reOpenCurrent();
}

/* load geo objects with an AJAX request */
function loadGeoObjects(){
    if (!first){ updateCheckedCategories(); }
    else if (p_checked_categories){
        checked_categories = p_checked_categories.join('_');
    }
    first = false;
    /* 0 stand for all categories */
    if (!checked_categories) checked_categories = '0';
    var uri = extra_url + "getGeoObjects/" + checked_categories;
    if (display_submited) uri += "/A_S";
    OpenLayers.loadURL(uri, '', this, setGeoObjects);
}

/* update the marker and vector layers from an http response GeoJSON */
function setGeoObjects(response){
    if(layerMarkers) layerMarkers.destroy();
    if(layerVectors) layerVectors.destroy();
    if (response.responseText.indexOf('no results') == -1) {
        /* clean the marker layer */
        if (currentPopup) {
            currentPopup.hide();
            if (!simple){
                hide('detail');
            }
        }
        layerVectors = new OpenLayers.Layer.Vector("Vector Layer");
        map.addLayer(layerVectors);
        layerVectors.setOpacity(0.8);
        layerMarkers = new OpenLayers.Layer.Markers('POIs');
        map.addLayer(layerMarkers);
        layerMarkers.setOpacity(0.8);

        var json = new OpenLayers.Format.JSON();
        var geo_objects = json.read(response.responseText);
        /* load every geo object */
        loadLayersFromJSON(layerMarkers, layerVectors, geo_objects);
        /*
        var geojson = new OpenLayers.Format.GeoJSON();
        var markers_pt = geojson.read(response.responseText);
        for (var i = 0; i < markers_pt.length; i++) {
            putMarker2(markers_pt[i]);
        }*/
    }
}

/* put a route on the map */
function putRoute(layer, route) {
    var polyline = route.geometry;
    var point_array = new Array();
    for (i=0; i<polyline.coordinates.length; i++){
        var point = new OpenLayers.Geometry.Point(polyline.coordinates[i][0],
                                                  polyline.coordinates[i][1]);
        point_array.push(point);
    }
    var linestring = new OpenLayers.Geometry.LineString(point_array);
    linestring.transform(epsg_display_projection, map.getProjectionObject());
    currentFeature = new OpenLayers.Feature.Vector();

    var style = OpenLayers.Util.extend({},
                                OpenLayers.Feature.Vector.style['default']);
    style.strokeColor = route.properties.color;
    style.strokeWidth = 3;
    currentFeature.style = style;
    currentFeature.geometry = linestring;
    layer.addFeatures([currentFeature]);
}


/* put a marker on the map */
function putMarker(layer, mark) {
    /* initialise a new marker with appropriate attribute for setting a
    marker */
    lat = mark.geometry.coordinates[1];
    lon = mark.geometry.coordinates[0];
    var size = new OpenLayers.Size(mark.properties.icon_width,
                                   mark.properties.icon_height);
    iconclone = new OpenLayers.Icon(media_path + mark.properties.icon_path,
                                    size, offset);
    var feature = new OpenLayers.Feature(markers,
              new OpenLayers.LonLat(lon, lat).transform(epsg_display_projection,
                                                        epsg_projection),
              {icon:iconclone});
    /*feature.closeBox = false;*/
    feature.pk = mark.properties.pk;
    feature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud);
    feature.data.popupContentHTML = "<div class='cloud'>";
    feature.data.popupContentHTML += mark.properties.name;
    feature.data.popupContentHTML += "</div>";
    feature.data.overflow = 'hidden';
    var marker = feature.createMarker();
    /* manage markers events */
    var markerClick = function (evt) {
        currentFeature = this;
        if (clicked) {
            if (currentPopup == this.popup) {
                this.popup.hide();
                clicked = false;
                if (!simple){
                    hide('detail');
                }
            } else {
                currentPopup.hide();
                showPop(this);
                updateDetail(this.pk);
            }
        } else {
            showPop(this);
            clicked = true;
            updateDetail(this.pk);
        }
        OpenLayers.Event.stop(evt);
    };
    var markerOver = function (evt) {
        document.body.style.cursor='pointer';
        OpenLayers.Event.stop(evt);
    };
    var markerOut = function (evt) {
        document.body.style.cursor='auto';
        OpenLayers.Event.stop(evt);
    };
    marker.events.register('click', feature, markerClick);
    marker.events.register('mouseover', feature, markerOver);
    marker.events.register('mouseout', feature, markerOut);
    layer.addMarker(marker);
    /* show the item when designed in the permalink */
    if (p_current_feature == feature.pk){
        p_current_feature = null;
        showPop(feature);
        clicked = true;
        updateDetail(feature.pk);
        map.setCenter(feature.lonlat, 17);
        updateCategories();
    }
    return feature;
}

var hidePopUp = function (evt) {
    if (clicked) {
        currentPopup.hide();
        clicked = false;
        if (!simple){
            hide('detail');
        }
    }
}

var refreshMapItems = function (evt) {
    loadCategories();
}

/* update current detail panel with an AJAX request */
function updateDetail(pk){
    var uri = extra_url + "getDetail/" + pk;
    if (simple){uri += "/?simple=True"}
    OpenLayers.loadURL(uri, '', this, setDetail);
}

/* update the detail panel from an http response */
function setDetail(response){
    if (response.responseText.indexOf('no results') == -1) {
        if (!simple){
            document.getElementById('detail').innerHTML = response.responseText;
            show('detail');
        } else {
            currentPopup.setContentHTML("<div class='cloud'>" +
                                              response.responseText + "</div>");
        }
    }
}

/* show the detail of a category */
function displayCategoryDetail(category_id) {
    var uri = extra_url + "getDescriptionDetail/" + category_id;
    OpenLayers.loadURL(uri, '', this, setCategoryDetail);
}

/* update the category detail panel from an http response */
function setCategoryDetail(response){
    if (response.responseText.indexOf('no results') == -1) {
        document.getElementById('category_detail').innerHTML = 
                                                response.responseText;
        show('category_detail');
    }
}

/* new permalink createParams method - update when facilities are given to
personalize the permalink */
function createParams(center, zoom, layers) {
    center = center || this.map.getCenter();
    var params = OpenLayers.Util.getParameters(this.base);
    // If there's still no center, map is not initialized yet.
    // Break out of this function, and simply return the params from the
    // base link.
    if (center) {
        center.transform(epsg_projection, epsg_display_projection);
        //zoom
        params.zoom = zoom || this.map.getZoom();
        //lon,lat
        var lat = center.lat;
        var lon = center.lon;
        params.lat = Math.round(lat*100000)/100000;
        params.lon = Math.round(lon*100000)/100000;
        //layers
        layers = layers || this.map.layers;
        params.layers = '';
        for (var i=0, len=layers.length; i<len; i++) {
            var layer = layers[i];

            if (layer.isBaseLayer) {
                params.layers += (layer == this.map.baseLayer) ? "B" : "0";
            } else {
                params.layers += (layer.getVisibility()) ? "T" : "F";
            }
        }
        /* only piece of code added */
        params.checked_categories = checked_categories;
        params.display_submited = display_submited;
        if(currentFeature){
            params.current_feature = currentFeature.pk;
        }
    }
    return params;
}

/* main initialisation function */
function init(){
    /* set the main map */
    var options = {
        controls:[new OpenLayers.Control.Navigation(),
                  new OpenLayers.Control.PanPanel(),
                  new OpenLayers.Control.ZoomPanel(),
                  new OpenLayers.Control.ScaleLine()],
        maxResolution: 156543.0399,
        units: 'm',
        projection: new OpenLayers.Projection('EPSG:4326'),
        theme:null
    };
    if (restricted_extent){
        restricted_extent.transform(epsg_display_projection, epsg_projection);
        options['restrictedExtent'] = restricted_extent;
    }
    map = new OpenLayers.Map('map', options);
    permalink = new OpenLayers.Control.Permalink("permalink");
    permalink.createParams = createParams;
    map.addControl(permalink);
    // update with the translated permalink label
    if(permalink_label && permalink.div && permalink.div.childNodes.length > 0){
        permalink.div.childNodes[0].textContent = permalink_label;
    }
    map.addLayers([map_layer]);

    map.events.register('click', map, hidePopUp);
    if (dynamic_categories){
        map.events.register('moveend', map, refreshMapItems);
    }
    /* if from a permalink */
    if (p_zoom) {
        var p_centerLonLat = new OpenLayers.LonLat(p_lon, p_lat);
        p_centerLonLat.transform(epsg_display_projection, epsg_projection);
        map.setCenter(p_centerLonLat, p_zoom);
        if (p_display_submited) {
            document.getElementById('display_submited_check').checked = true;
        }
        if (p_checked_categories){
            /* ckeck selected categories and uncheck others */
            inputs = window.document.forms["frm_categories"];
            for (var i = 0; i < inputs.length; i++) {
                input = inputs[i];
                if (input.name.substring(9, 0) == 'category_'){
                    id = input.name.substring(9, input.name.length);
                    input.checked = false;
                    for (var cc=0; cc < p_checked_categories.length; cc++){
                        if (p_checked_categories[cc] == id){
                            input.checked = true;
                        }
                    }
                }
            }
            checked_categories = p_checked_categories.join('_');
        }
    }
    /* if not zoom to the extent in cookies */
    else if (!zoomToCurrentExtent(map)){
        /* if no extent in cookies zoom to default */
        map.setCenter(centerLonLat, 13);
    }
    loadCategories();
    loadGeoObjects();
}

