// Please keep this file indented with OpenLayers (or MapFish) coding style.

// We define some useful namespaces:
Ext.namespace('gis', 'gis.poi', 'gis.route', 'gis.valley', 'gis.util', 'gis.admin');

Ext.BLANK_IMAGE_URL = '/js/mfbase/ext-2.2/resources/images/default/s.gif';
OpenLayers.ProxyHost = '/cgi-bin/proxy.cgi/?url='; 
OpenLayers.ImgPath = '/js/mfbase/openlayers/img/';
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";
OpenLayers.Lang.setCode(lang); // lang set in HTML via server.
gis.bootstrap = {};
gis.initialZoomLevel = 9;
gis.baseURL = ''; // might be replaced by '/index.php' or just '' or '/frontend_dev.php'
gis.owsUrl = "/cgi-bin/ows.cgi";
gis.wmscUrl = "/tilecache/tilecache.py";
gis.initialCenter = new OpenLayers.LonLat(793000, 5503160);
gis.tm = null; // timeout
gis.overFeature = null;

    
//// récupère un objet filtre dans le JSON
//gis.util.getFilterValues = function(targetName){
//    var filter;
//	for (var i=0;i<=gis.bootstrap.filters.length;i++)
//	{
//		filter = gis.bootstrap.filters[i];
//		if (filter.name == targetName)
//			return filter;	
//	}
//	return null;
//}

// opens an html popup, with route/print/id/X inside
gis.route.print = function() {
    if (gis.route.selectedId) {
        window.open('/route/print/'+gis.route.selectedId,'print','location=no,menubar=yes,status=no,scrollbars=yes,width=850,height=600');
    }
}


gis.route.reset = function() {
    gis.route.resetButton.disable();
    if (!authenticated) gis.route.tbResetButton.disable();
    gis.route.gridSm.clearSelections();
    var components = gis.route.form.findByType('combo');
    for (var i=0;i<components.length;i++) {
        components[i].reset();
    }
    gis.route.dataStore.clearFilter();
    if (gis.poi.hoverControl) {
        gis.poi.hoverControl.deactivate();
    }
    gis.toolbar.disable();
    gis.route.descriptionPanel.hide();
    gis.poi.descriptionPanel.hide();
    gis.route.searchPanel.expand();
    gis.poi.layer.setVisibility(false);
    gis.poi.deleteAll();
    gis.map.setCenter(gis.initialCenter, gis.initialZoomLevel);
}

// application des filtres sur les itinéraires
gis.listSelect = function(myList) {
    gis.route.resetButton.enable();
    if (!authenticated) gis.route.tbResetButton.enable();
    // we first unselect any selected item
	gis.route.gridSm.clearSelections();
    // we filter the datastore
	gis.route.dataStore.filterBy(gis.recordFilter);
    // we zoom to filtered items
    var bbArray = gis.route.dataStore.collect('bbox');
    if (bbArray.length) {
        var bounds = OpenLayers.Bounds.fromString(bbArray[0]);
        for (var i = 1; i < bbArray.length; i++) {
            bounds.extend(OpenLayers.Bounds.fromString(bbArray[i]));
        }
        gis.map.zoomToExtent(bounds);
    }
    // note : SLD is being applied by a listener on store's "datachanged" event
}

// calcul du résultat du filtre sur les itinéraires
gis.recordFilter = function(rec, id) {
    var components = gis.route.form.findByType('combo');
    // initialisation du résultat à true.
    // les lignes ne respectant pas les filtres le mettront à false
    var result = true;
    var c, val, inCat;
    
    for (var i = 0; i < components.length; i++)
    {
    	c = components[i];
    	val = c.getValue();
    	if (val != '' && val != 'null')
    	{
    		// traitement des valeurs discrètes
    		if (val.toString().indexOf('|')!=-1)
    		{
    			vals = val.split('|');
    			if (rec.get(c.id) < vals[0] || rec.get(c.id)> vals[1])
    				result = false;
    		}
    		else {
    			// traitement des catégories (tableau d'ids)
    			if (c.id == 'categories' || c.id == 'valley'){
    				inCat = false;
                    for (var j=0;j<rec.get(c.id).length;j++)
                     {
						if (rec.get(c.id)[j] == val){
							inCat = true;
						}
					}
					if (!inCat) result = false;
    			}
    			// traitement standard
    			else {	
    				if (rec.get(c.id) != val)
    					result = false;
    			}
    		}
    	}
    	
    	// sortie des tests dès qu'une condition est fausse
    	if (!result) {
    		return result;
        }
    }
    // result est forcément vrai ici
	return result;
}

gis.util.showErrorMsg = function(errorMsg) {
    Ext.Msg.show({
        title: globalLabels.AjaxErrorTitle,
        msg: errorMsg,
        buttons: Ext.Msg.OK,
        icon: Ext.MessageBox.ERROR
    });
    return;
}

gis.valley.getNameFromId = function(idValley) {
    if (gis.bootstrap && gis.bootstrap.filters) {
        for (var i=0;i<gis.bootstrap.filters.length;i++) {
            f = gis.bootstrap.filters[i];
            if (f.name == 'valley') {
                for (var j=0;j<f.kv.length;j++) {
                    v = f.kv[j];
                    if (v.id == idValley) {
                        return v.value;
                    }
                }
            }
        }
    }
    return '';
}

// contruction des listes de filtres à partir d'un objet filtre du JSON
gis.addFilter = function(FilterForm, aFilter) {
    if (aFilter.type == 'combobox') {
        aFilter.kv.unshift({
            "label": globalLabels.blankItemForFilters,
            "value": "null"
        });
        var combo = new Ext.form.ComboBox({
	        id: aFilter.name,
	        fieldLabel: aFilter.title,
	        displayField: 'label',
	        valueField: 'value',
	        width: 140, 
	        listeners: {select: gis.listSelect},
	        height: 30,
	        editable: false,
	        typeAhead: true,
	        mode: 'local',
	        forceSelection: true, // FIXME: set to false ?
	        triggerAction: 'all',
	        emptyText: globalLabels.pickaValueLabel,
	        selectOnFocus: true,
	        store: new Ext.data.JsonStore({
			    data: aFilter,
			    root: 'kv',
			    fields: ['value', 'label']
			})
	    });
	    gis.route.form.add(combo);
    }
}

/*
    Fonction de chargement des détails d'un itinéaire
       sm : Ext.SelectionModel
       rIdx : Row index sélectionné
       r : row
       
    Fait une requête Ajax sur routes/highlight pour récupérer le flux JSON correspondant.
            (voir js/routes.highlight.sample.json pour la structure)
*/
gis.route.getInfo = function(sm, rIdx, r) {

    // remove displayed POIs
    gis.poi.deleteAll();
    
    gis.route.resetButton.enable();
    
    // zoom to route
    var coords = r.get("bbox").split(',');
    var delta = 0;
    var mybb = new OpenLayers.Bounds(
        parseInt(coords[0]) - delta,
        parseInt(coords[1]) - delta,
        parseInt(coords[2]) + delta,
        parseInt(coords[3]) + delta
    );
    gis.map.zoomToExtent(mybb);
    
    gis.route.descriptionPanel.show();
    gis.route.descriptionPanel.expand();
    gis.route.descriptionMask.show();
    
    gis.route.selectedId = r.get('id');
    // AJAX request to fill side panel
    Ext.Ajax.request({
        url: gis.baseURL + '/routes/highlight',
        method: 'GET',
        disableCaching: (authenticated == 1),
        params: {
            selected: gis.route.selectedId,
            listed: gis.route.dataStore.collect('id').sort().join(','),
            lang: lang // only for client cache control
        },
        success: function(res,opt) {
		   	// affectation de la réponse à un objet global
            try {
                eval('var response = ' + res.responseText);
            } catch(e) {
                gis.util.showErrorMsg(globalLabels.AjaxErrorText1);
            }
            // application du nouveau SLD :
            gis.route.layer.mergeNewParams({
                sld: unescape(response.UrlSLD)
            });
            
            //gis.route.descriptionPanel.show();
            
            // mise à jour de la description de l'itinéraire --------------------------------
            gis.route.descriptionMask.hide();
            if (response.route.picture) {
                gis.route.tplWithImage.overwrite(gis.route.descriptionPanel.body, response.route);
            } else {
                gis.route.tplWithoutImage.overwrite(gis.route.descriptionPanel.body, response.route);
            }
            gis.route.button.enable();
            if (!authenticated) {
                gis.route.permalink.enable();
            }
            //gis.route.descriptionPanel.expand();
            
            if (gis.toolbar.disabled) {
                gis.toolbar.enable();
            }
            gis.poi.layer.setVisibility(true);
            
            // Affichage des POI sur la carte            
            var p, f, val, renderIntent;
            
            // we add the POI hoverControl if necessary
            if ((gis.poi.hoverControl) && (!gis.poi.hoverControl.map)) {
                gis.map.addControl(gis.poi.hoverControl); 
            }
            
            // this is because hover control can be deactivated on reset :
            if ((gis.poi.hoverControl) && (gis.poi.hoverControl.map) && (!gis.poi.hoverControl.active)) {
                gis.poi.hoverControl.activate();
            }
            
            var checked = [];
            for (var i=1; i<7; i++) {
                checked[i] = (authenticated) ? true : Ext.get('cbx_'+ i).dom.checked;
            }
            
            for (var i=0; i < response.points.length; i++){
                p = response.points[i];

                val = gis.poi.getTypeName(p.properties.type);
                p.properties.picto = '/images/'+val+'_20x20.png'; 
                    
                f = new OpenLayers.Feature.Vector(
                    new OpenLayers.Geometry.Point(
                        p.geometry.coordinates[0], 
                        p.geometry.coordinates[1]
                    ),
                    p.properties
                );
                f.fid = p.properties.id;
                
                gis.poi.layer.addFeatures([f]);
                
                renderIntent = (checked[p.properties.type]) ? "default" : "hidden";
                gis.poi.layer.drawFeature(f, renderIntent);
            }
        },
        failure: function(res,opt) {
            gis.route.descriptionMask.hide();
            gis.util.showErrorMsg(globalLabels.AjaxErrorText1);
            return;
        }
    });
}


gis.poi.showInfo = function(fid) {
    gis.poi.descriptionPanel.show();
    gis.poi.descriptionPanel.expand();
    gis.poi.descriptionMask.show();
    Ext.Ajax.request({
        url: gis.baseURL + '/pois/view',
        method: 'GET',
        disableCaching: (authenticated == 1),
        params: {
            id: fid,
            lang: lang // only for client cache control
        },
        success: function(res,opt) {
            eval('var details = ' + res.responseText);
            gis.poi.descriptionMask.hide();
            if (details.picture) {
                gis.poi.tplWithImage.overwrite(gis.poi.descriptionPanel.body, details);
            } else {
                gis.poi.tplWithoutImage.overwrite(gis.poi.descriptionPanel.body, details);
            }
        },
        failure: function(res,opt) {
            gis.poi.descriptionMask.hide();
            gis.util.showErrorMsg(globalLabels.AjaxErrorMessage);
            return;
        }
    });
}

gis.poi.preparePopup = function(feature) {
    if (gis.tm) {
        clearTimeout(gis.tm);
    }
    gis.overFeature = feature;
    
    //gis.tm = setTimeout("gis.poi.createPopup()", 100);
    gis.tm = setTimeout("gis.poi.createPopup()", 0);
}

gis.poi.createPopup = function() {
    if (gis.poi.popup) {
        gis.poi.deletePopup();
    }
    var lonlat = new OpenLayers.LonLat(gis.overFeature.geometry.x , gis.overFeature.geometry.y );
    var html = '<div style="text-align:center;"><span style="font-size:small"><b>' + gis.overFeature.attributes["name"] + ' </b></span>';
    html += (gis.overFeature.attributes["picture"]) ? 
        '<br /><img src="/uploads/images/thumbnails/' + gis.overFeature.attributes["picture"] + '" alt="" style="width:100px;height:100px;padding:5px;" /></div>' : '</div>' ;
    var anchor = {'size': new OpenLayers.Size(20,20), 'offset': new OpenLayers.Pixel(-10,-10) };
    gis.poi.popup = new OpenLayers.Popup.AutoSizedFramedCloud("popup", lonlat, null, html, anchor, false);
    gis.poi.popup.fixedRelativePosition = true;
    gis.map.addPopup(gis.poi.popup, true);
}

gis.poi.deletePopup = function(){
    gis.map.removePopup(gis.poi.popup);
    gis.poi.popup = null;
}

gis.poi.getTypeName = function(TypeId){
    var val = '';
    switch (TypeId) { 
        case 1:
            val = 'lakes';
            break;
        case 2:
            val = 'huts';
            break;
        case 3:
            val = 'passes';
            break;
        case 4:
            val = 'summits';
            break;
        case 5:
            val = 'nature';
            break;
        case 6:
            val = 'culture';
            break;
        default:
            // should not happen
            break;    
    }
    return val;
}

gis.poi.deleteAll = function() {
    gis.poi.layer.destroyFeatures();
}

// This function only applies SLD to get routes in gray/yellow.
// It does not handle highlighting.
gis.route.applyNewSLD = function(idArray) {
    Ext.Ajax.request({
        url: gis.baseURL + '/routes/filter',
        method: 'GET',
        disableCaching: false,
        params: { 
            ids: idArray.sort().join(',')
        },
        success: function(res,opt) {
            eval('var filterParam = ' + res.responseText);
            gis.route.layer.mergeNewParams({
                sld: unescape(filterParam.UrlSLD)
            }); // here, at startup, layer wont be redrawn nor added to the map, since it is not already associated to gis.map
            if (!gis.route.layer.map) {
                gis.map.addLayer(gis.route.layer);
            }
        },
        failure: function(res,opt) {
            gis.util.showErrorMsg(globalLabels.sldLoadindError);
            return;
        }
    });
}



// template HTML d'affichage de la description de l'itinéraire :
gis.route.tplWithImage = new Ext.Template([
    '<div style="text-align:center;margin:5px;"><b>{name}</b><br />',
    '<img src="/uploads/images/originals/{picture}" alt="" style="border:solid 2px #ffffff;padding:5px;"/></div>',
    '<div style="text-align:left;margin:5px;">',
    '<b>' + globalLabels.colBestPeriod + ' :</b> {best_period_from} - {best_period_to}<br/>',
    '<b>' + globalLabels.colAlt + ' :</b> {elevation_start}, {elevation_max}<br/>',
    '<b>' + globalLabels.colCity + ' :</b> {city_start}<br/>',
    '<div style="text-align:justify;"><b>' + globalLabels.colTransport + '</b> : {public_transportation_access}</div><br/><br/>',
    '<div style="text-align:justify;">{description}</div><br/></div>'
]);

gis.route.tplWithoutImage = new Ext.Template([
    '<div style="text-align:center;margin:5px;"><b>{name}</b></div>',
    '<div style="text-align:left;margin:5px;">',
    '<b>' + globalLabels.colBestPeriod + ' :</b> {best_period_from} - {best_period_to}<br/>',
    '<b>' + globalLabels.colAlt + ' :</b> {elevation_start}, {elevation_max}<br/>',
    '<b>' + globalLabels.colCity + ' :</b> {city_start}<br/>',
    '<div style="text-align:justify;"><b>' + globalLabels.colTransport + '</b> : {public_transportation_access}</div><br/><br/>',
    '<div style="text-align:justify;">{description}</div><br/></div>'
]);
    
// template HTML d'affichage de la description de l'itinéraire :
gis.poi.tplWithImage = new Ext.Template([
    '<div style="text-align:center;margin:5px;"><b>{name}</b> ({elevation})</div>',
    '<img src="/uploads/images/originals/{picture}" alt="" style="border:solid 2px #ffffff;padding:5px;"/>',
    '<div style="text-align:left;margin:5px;">',
    '<div style="text-align:justify;">{description}</div><br/></div>'
]);

gis.poi.tplWithoutImage = new Ext.Template([
    '<div style="text-align:center;margin:5px;"><b>{name}</b> ({elevation})</div>',
    '<div style="text-align:left;margin:5px;">',
    '<div style="text-align:justify;">{description}</div><br/></div>'
]);


gis.valley.clicked = function(feature) {
    // we zoom to valley bounds
    gis.map.zoomToExtent(
        new OpenLayers.Bounds(
            feature.data.left, 
            feature.data.bottom, 
            feature.data.right, 
            feature.data.top
        )
    );
    // we set the valley combobox accordingly
    el = Ext.getCmp('valley');
    el.setValue(gis.valley.nameCache[feature.fid], false);
    gis.listSelect(el);
};


gis.populateToolbar = function(){
    gis.toolbar.add(' ');
    gis.toolbar.addField(
        new Ext.form.Label({text: globalLabels.display})
    );
    gis.toolbar.add(' ');
    
    for (var i=1;i<7;i++) {
        var val = gis.poi.getTypeName(i);
        gis.toolbar.addField(
            new Ext.form.Checkbox({
                id: 'cbx_'+i,
                name: i.toString(),
                checked: true, //(i==2 || i==4), // to allow initial display of summits and huts
                listeners: {
                    'check': function(cb, checked) {
                        var features = gis.poi.layer.features;
                        for (var i=0;i<features.length;i++) {
                            if (features[i].attributes["type"] == cb.name) {
                                var renderIntent = checked ? "default" : "hidden";
                                gis.poi.layer.drawFeature(features[i], renderIntent);
                            }
                        }
                    }
                }
            })
        );
        gis.toolbar.add(' ');
        gis.toolbar.addField(
            new Ext.form.Label({
                html: '<img src="/images/'+val+'_20x20.png" alt="" /> '
            })
        );
        gis.toolbar.add(' ');
        gis.toolbar.addField(
            new Ext.form.Label({text: globalLabels[val]})
        );
        gis.toolbar.add(' &nbsp; ');
    }
    gis.toolbar.add('->');
    
    // RAZ button
    gis.route.tbResetButton = gis.toolbar.addButton({
        text: globalLabels.RAZ,
        handler: gis.route.reset,
        iconCls: 'resetButton'
    });
    
    gis.toolbar.activate();
}



    gis.route.southPanel = new Ext.Panel({
        region: 'south',
        layout: 'fit',
        title: globalLabels.routesTitle,
        collapsible: true,
        collapsed: false,
        bodyStyle: "background-color:transparent; background-image:url('/images/transparent_25.png');",
        split: true,
        height: 170,
        minSize: 100,
        maxSize: 500,
        margins: '5 0 0 0',
        iconCls: 'routeGridPanel'
    });

    // Formulaire contenant les filtres de sélection des itinéraires.
    // Initialisé avec une liste factice, puis rempli après le chargement du bootstrap.json par
    // la fonction gis.addFilter
    gis.route.form = new Ext.form.FormPanel({
        id: 'form',
        border: false,
        style:'padding:5px',
        items: [{ // FIXME : try to replace this hack (fake form content, lately overwritten) ... this is dirty.
            id:'fake' 
        }]
    });
    
    gis.route.searchPanel = new Ext.Panel({
        id: 'routeSearchPanel',
        title: globalLabels.searchPanelTitle,
        iconCls: 'routeSearchPanel',
        border: false,
        items: [gis.route.form]
    });
    
    gis.route.resetButton = gis.route.searchPanel.addButton({
        text: globalLabels.RAZ,
        disabled: true,
        iconCls: 'resetButton',
        handler: gis.route.reset
   	});
        
    gis.route.descriptionPanel = new Ext.Panel({
        id: 'routeDescriptionPanel',
        title: globalLabels.routeDescriptionPanelTitle,
        html: '',
        bodyStyle: "background-color:transparent; background-image:url('/images/transparent_75.png');",
        iconCls: 'routeDescriptionPanel',
        autoScroll:true,
        border: false,
        hidden: true
    });
    
    gis.route.button = gis.route.descriptionPanel.addButton({
        text: (authenticated == 1) ? globalLabels.edit : globalLabels.print,
        disabled: true,
        iconCls: (authenticated == 1) ? 'routeEditButton' : 'printButton',
        handler: function() {
            if (authenticated == 1) {
                gis.admin.generateEditForm();
            } else {
                gis.route.print();
            }
        }
    });
    
    if (authenticated == 0) {
        gis.route.permalink = gis.route.descriptionPanel.addButton({
            text: globalLabels.permalink,
            disabled: true,
            iconCls: 'permalinkButton',
            handler: function() {
                var permalinkUrl = 'http://' + window.location.hostname + '/route/'+lang+'/' + gis.route.selectedId.toString() + '.html';
                Ext.Msg.show({
                    title: globalLabels.permalink,
                    msg: globalLabels.permalinkText + ' <br/><a href="' + permalinkUrl + '">' + permalinkUrl + '</a>',
                    buttons: Ext.Msg.OK,
                    icon: Ext.MessageBox.INFO
                });
            }
        });
    }
    
    gis.poi.descriptionPanel = new Ext.Panel({
        id: 'poiDescriptionPanel',
        title: globalLabels.poiDescriptionPanelTitle,
        html: '',
        iconCls: 'poiDescriptionPanel',
        autoScroll:true,
        border: false,
        bodyStyle: "background-color:transparent; background-image:url('/images/transparent_75.png');",
        hidden: true
    });

// buggy:
//Ext.onReady(function() {
function init() {

    // fonction de chargement du flux JSON d'initialisation
    Ext.Ajax.request({
		url: gis.baseURL + '/bootstrap',
        method: 'GET',
        disableCaching: false,
        params: { 
            'auth': authenticated,
            'lang': lang // only for caching reasons ...
        },
		success: function(res, opt) {
            // affectation de la réponse à un objet global
            eval('gis.bootstrap = ' + res.responseText);
            
            // mise à jour du tableau des itinéraires
            gis.route.dataStore = new Ext.data.JsonStore({
                root: 'routes',
                fields: ['id', 'bbox', 'name', 'height_diff', 'duration', 'loop', 'crossborder', 'valley', 'rating', 'categories'],
                autoLoad: true,
                data: gis.bootstrap,
                scope: this, 
                listeners: {
                    "datachanged": function() {
                        // we apply the SLD to get routes in yellow and gray
                        // except if we have a permalink request ...
                        gis.route.applyNewSLD(this.collect('id'));
                        // we update gridPanel's title with item number
                        var nb = this.getCount();
                        var title = '';
                        switch (nb) {
                            case 0:
                                title = globalLabels.noRouteTitle;
                                break;
                            case 1:
                                title = '1 ' + globalLabels.routeTitle;
                                break;
                            default:
                                title = nb + ' ' + globalLabels.routesTitle;
                                break;
                        };
                        gis.route.southPanel.setTitle(title);
                    }
                }
            });
            
            var colModel = new Ext.grid.ColumnModel([{
                id: "name",
                header: globalLabels.colName, 
                width: 350,
                sortable: true, 
                dataIndex: 'name'
            },{
                header: globalLabels.colHeightDiff, 
                width: 100, 
                sortable: true, 
                dataIndex: 'height_diff'
            },{
                header: globalLabels.colDuration, 
                width: 100, 
                sortable: true, 
                dataIndex: 'duration'
            },{
                header: globalLabels.colRating, 
                width: 100, 
                sortable: true, 
                dataIndex: 'rating'
            },{
                header: globalLabels.colValley, 
                width: 400, 
                sortable: true, 
                dataIndex: 'valley'
            }]);
            
            gis.route.gridSm = new Ext.grid.RowSelectionModel({
                singleSelect: true,
                listeners: {
                    "rowselect": gis.route.getInfo
                }
            });
        
            gis.route.gridPanel = new Ext.grid.GridPanel({
                store: gis.route.dataStore,
                colModel: colModel,
                viewConfig: {
                    forceFit: true
                },
                enableHdMenu: false,
                sm: gis.route.gridSm,
                frame: false,
                border: false                
                //style: 'background-color:transparent;'
            });
            
            gis.route.southPanel.add(gis.route.gridPanel);
            
            gis.route.form.remove('fake'); // FIXME : try to clean this.
            
            // parcours des objets filtres trouvés dans le JSON
            for (var i = 0; i < gis.bootstrap.filters.length; i++) {
                gis.addFilter(gis.route.form, gis.bootstrap.filters[i]);
            }
            
            // régénération du formulaire avec les nouveaux composants
            gis.viewport.doLayout();
            
            
            gis.formMask.hide();
            gis.gridPanelMask.hide();
            
            // récupération de l'id du permalink éventuel
            if (selected_route_id && selected_route_id > 0) { 
                gis.route.selectedId = selected_route_id;
                var rowIndex = gis.route.dataStore.find('id', selected_route_id);
                //console.log("we should display rowIndex " + rowIndex);
                //gis.route.gridSm.clearSelections();
                gis.route.gridSm.selectRow(parseInt(rowIndex));
                gis.route.gridPanel.getView().refresh(); // this is a try to fix no selection in array ..
            }
            
		},
		failure: function(res,opt){
            gis.util.showErrorMsg(globalLabels.AjaxErrorText1);
            return;
		}   
	});
    
    
    gis.map = new OpenLayers.Map('map', {
        projection: "epsg:900913",
        units: "m",
        theme: null,
        controls: [],
        numZoomLevels: 18,
        maxResolution: 156543.0339,
        minResolution: 1.1943285667419434,
        maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                            20037508.34, 20037508.34)
    });

    // create Google Mercator layer
    gis.gmap = new OpenLayers.Layer.Google(
        "Relief (Google)", {
            'type': G_PHYSICAL_MAP,
            'sphericalMercator': true
            //  google layer has 20 zoom levels (0 to 19) (from farther to closer)
        },{
            buffer: 0,
            minZoomLevel: 0,
            maxZoomLevel: 17
            // we therefore limit the number of zoom levels to 18
        }
    );
    
    gis.ortho = new OpenLayers.Layer.WMS("Photos aériennes", [
            'http://t1.' + raster_wms_server + gis.wmscUrl,
            'http://t2.' + raster_wms_server + gis.wmscUrl,
            'http://t3.' + raster_wms_server + gis.wmscUrl
        ],{
            layers: 'ortho',
            srs: 'epsg:900913',
            format: 'image/jpeg'
        },{
            visibility: true,
            isBaseLayer: true,
            buffer: 1,
            transitionEffect: 'resize',
            numZoomLevels: 18,
            maxResolution: 156543.0339,
            minResolution: 1.1943285667419434,
            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                                20037508.34, 20037508.34)
        }
    );
    
    gis.commun = new OpenLayers.Layer.WMS("Relief et informations", [
            'http://t1.' + raster_wms_server + gis.wmscUrl,
            'http://t2.' + raster_wms_server + gis.wmscUrl,
            'http://t3.' + raster_wms_server + gis.wmscUrl
        ], {
            layers: 'commun',
            srs: 'epsg:900913',
            format: 'image/jpeg'
        },{
            visibility: true,
            isBaseLayer: true,
            buffer: 1,
            transitionEffect: 'resize',
            numZoomLevels: 18,
            maxResolution: 156543.0339,
            minResolution: 1.1943285667419434,
            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                                20037508.34, 20037508.34)
        }
    );

    gis.route.layer = new OpenLayers.Layer.WMS("Routes",
        gis.owsUrl, {
            layers: ['routes','listed_routes','selected_route'],
            srs: 'epsg:900913',
            format: 'image/png',
            transparent: true
        },{
            displayInLayerSwitcher: false,
            visibility: true,
            isBaseLayer: false,
            singleTile: true,
            maxResolution: 152.87405654296876, 
            minResolution: 1.1943285667419434,
            alpha: true, // alpha hack here for IE6 !
            ratio: 2
            //transitionEffect: 'resize' // because of a bad OL support for now ...
        }
    );
    
    
    gis.valley.layer = new OpenLayers.Layer.WMS("Valleys", [
            'http://t1.' + raster_wms_server + gis.wmscUrl,
            'http://t2.' + raster_wms_server + gis.wmscUrl,
            'http://t3.' + raster_wms_server + gis.wmscUrl
        ],{
            layers: ['valleys'],
            srs: 'epsg:900913',
            format: 'image/png',
            transparent: true
        },{
            displayInLayerSwitcher: false,
            visibility: true,
            isBaseLayer: false,
            singleTile: false,
            minScale: 750000, // => "grandes échelles" seulement
            alpha: true, // alpha hack here for IE6 !
            buffer: 1
        }
    );
    
    /*
    GML is got from a request such as: /cgi-bin/ows.cgi?typename=valleys&srs=epsg%3A900913&SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&SRS=epsg%3A900913&BBOX=0,1000000,1000000,10000000
    DONE : applied some simplification over WFS output : 43 kb data was too much at this scale ... reduced to 23kb at 300m simplification level
    TODO : in deploy script, or somewhere else, wget this URL, and create the static GML file ?
    */
    gis.valley.vectorLayer = new OpenLayers.Layer.GML("Valley Selection", 
        '/valleys_300m.gml', {
            styleMap: new OpenLayers.StyleMap({
                "default": new OpenLayers.Style({
                    fillOpacity: 0.1,
                    strokeColor: "#680404",
                    fillColor: "#680404",
                    strokeWidth: 2,
                    cursor: 'pointer'
                }),
                "select": new OpenLayers.Style({
                    fillOpacity: 0.4
                })
            }),
            displayInLayerSwitcher: false,
            visibility: true,
            isBaseLayer: false,
            maxScale: 750000, // this is just for it to appear at one zoom level !
            minScale: 1500000
        }
    );
    
    /* Configuration de la couches des POI */
    var poiStyles = new OpenLayers.StyleMap({
                "default": new OpenLayers.Style({
                    externalGraphic: "${picto}",
                    backgroundGraphic: "/images/shadow.png",
                    backgroundXOffset: 9,
                    backgroundYOffset: -8,
                    graphicWidth: 20,
                    graphicHeight: 20,
                    cursor: 'pointer'
                }),
                "select": new OpenLayers.Style({
                    graphicWidth: 24,
                    graphicHeight: 24
                }),
                "hidden": new OpenLayers.Style({
                    graphicWidth: 0,
                    graphicHeight: 0
                })
    });
    
    // création de la couche des POI
    gis.poi.layer = new OpenLayers.Layer.Vector("POI", {
        displayInLayerSwitcher: false,
        styleMap: poiStyles,
        visibility: false,
        minScale: 750000
    });
    // not yet added to map !
    
    if (!authenticated) {
        gis.poi.hoverControl = new OpenLayers.Control.Hover(
                    gis.poi.layer, {
                        overFeature: function(feature) {
                            gis.poi.preparePopup(feature);
                        },
                        outFeature: function(feature) {
                            if (gis.tm) {
                                clearTimeout(gis.tm);
                            }
                            if (gis.poi.popup) {
                                gis.tm = setTimeout("gis.poi.deletePopup()", 1000);
                            }
                        },
                        clickFeature: function(feature) {
                            gis.poi.showInfo(feature.fid);
                        },
                        clickoutFeature: function(feature) {
                            gis.poi.layer.drawFeature(feature, "default");
                            // we also reopen route panel to hide POI info ...
                            gis.route.descriptionPanel.expand();
                        }
                    }
                );
    }
    // not yet added to map !
    
    gis.map.addLayers([gis.gmap, gis.ortho, gis.commun, /*gis.ortho_it, gis.ortho_fr, */ gis.valley.layer, gis.valley.vectorLayer, gis.poi.layer]);
    
  
    gis.valley.centroidCache = new Array();
    gis.valley.nameCache = new Array();
  
    gis.valley.hoverControl = new OpenLayers.Control.Hover(
        gis.valley.vectorLayer, {
            overFeature: function(feature) {
                gis.valley.vectorLayer.drawFeature(feature, "select");
                // we add a popup with valley name inside ...
                if (!(gis.valley.nameCache[feature.fid])) {
                    gis.valley.nameCache[feature.fid] = gis.valley.getNameFromId(
                        parseInt(feature.data.id)
                    );
                    gis.valley.centroidCache[feature.fid] = new OpenLayers.LonLat(
                        (parseInt(feature.data.left) + parseInt(feature.data.right))/2,
                        (parseInt(feature.data.bottom) + parseInt(feature.data.top))/2
                    );
                }
                gis.valley.popup = new OpenLayers.Popup.AutoSizedFramedCloud(
                    "valley_popup", 
                    gis.valley.centroidCache[feature.fid], 
                    null, 
                    '<span style="font-size:small"><b>' + gis.valley.nameCache[feature.fid] + '</b></span>', 
                    OpenLayers.Util.extend(feature, {
                        'size': new OpenLayers.Size(10,10), 
                        'offset': new OpenLayers.Pixel(0,0)
                    }),
                    false
                );
                gis.valley.popup.events.register("mousemove", gis.valley.popup, function(evt){
                    gis.valley.vectorLayer.drawFeature(this.anchor, "select");
                });
                gis.valley.popup.events.register("mouseout", gis.valley.popup, function(evt){
                    gis.valley.vectorLayer.drawFeature(this.anchor, "default");
                });
                gis.valley.popup.events.register("click", gis.valley.popup, function(evt){
                    gis.valley.clicked(this.anchor);
                });
                gis.map.addPopup(gis.valley.popup, true);
            },
            outFeature: function(feature) {
                gis.valley.vectorLayer.drawFeature(feature, "default");
            },
            clickFeature: gis.valley.clicked,
            clickoutFeature: function(feature) {
                gis.valley.popup.destroy();
            }
        }
    );

    gis.map.addControl(gis.valley.hoverControl);
    gis.valley.hoverControl.activate();

    // loading indicator ...
    gis.map.addControl(
        new OpenLayers.Control.LoadingPanel(
            null, {
                map: gis.map
            }
        )
    ); 
    
    // numerical scale
    gis.map.addControl(
        new OpenLayers.Control.Scale(null, {
            //title: 'Scale' // i18n ?
        })
    );

    gis.map.addControl(
        new OpenLayers.Control.PanZoomBar({
            title: globalLabels.panZoomBar
        })
    );
        
    gis.map.addControl(
        new OpenLayers.Control.ScaleLine({
            title: globalLabels.scaleLine
        })
    );
    
    //gis.map.addControl(new OpenLayers.Control.LayerSwitcher({}));
        
    var navControl = new OpenLayers.Control.Navigation({
            type: OpenLayers.Control.TYPE_TOGGLE,
            zoomWheelEnabled: true
    });
    navControl.handlers.wheel = new OpenLayers.Handler.MouseWheel(navControl, {});
    gis.map.addControl(navControl);
    navControl.activate();
        
    gis.toolbar = new mapfish.widgets.toolbar.Toolbar({
        map: gis.map, 
        configurable: false
    });
    
    // this is to fix a pb in mapfish.widgets.toolbar.Toolbar initComponent
    // (autoheight = true), which should'nt be there:
    gis.toolbar.autoHeight = false;
    gis.toolbar.height = 25;
        
    gis.map.setCenter(gis.initialCenter, gis.initialZoomLevel);
    
    gis.map.events.register('zoomend', this, function() {
        // remove any popup
        if (gis.map.popups[0]) {
            gis.map.popups[0].destroy();
        }

        var res = gis.map.getResolution();
        if (res <= 3) {
            gis.map.setBaseLayer(gis.ortho);
        } else if (res <= 12) {
            gis.map.setBaseLayer(gis.commun);
        } else {
            gis.map.setBaseLayer(gis.gmap);
        }
    });
    
    var htmlFooter = '<div id="realizedBy">'+globalLabels.madeBy+' <a target="_blank" href="http://www.camptocamp.com/">Camptocamp</a> / <a target="_blank" href="http://www.altimax.com/">Altimax</a></div><a href="/credits">'+globalLabels.credits+'</a> - <a href="/copyright">'+globalLabels.copyright+'</a> - ';
    htmlFooter += (authenticated) ? '<a href="/users/logout">'+globalLabels.disconnect+'</a>' : '<a href="/users/login">'+globalLabels.administration+'</a>';
        
    gis.viewport = new Ext.Viewport({
            layout: 'border',
            items: [
                new Ext.BoxComponent({
                    region: 'north',
                    el: 'north',
                    height: 114
                }),{
                    region: 'south',
                    el: 'south',
                    border: false,
                    html: htmlFooter,
                    margins: '5 0 0 0'
                },{
                    region: 'center',
                    el: 'center',
                    id: 'center',
                    border: false,
                    layout: 'border',
                    margins: '0 5 0 5',
                    items: [
                        {
                            region: 'west',
                            id: 'west-panel',
                            split: true,
                            border: true,
                            width: 325, 
                            minSize: 250,
                            maxSize: 600,
                            margins: '0 5 0 0',
                            layout: 'accordion',
                            layoutConfig: {
                                animate: true
                            },
                            items: [gis.route.searchPanel, gis.route.descriptionPanel, gis.poi.descriptionPanel]
                        },{
                            region: 'center',
                            layout: 'border',
                            border: false,
                            margins: '0 0 0 0',
                            items: [{
                                region: 'center',
                                layout: 'fit',
                                xtype: 'mapcomponent',
                                map: gis.map,
                                tbar: gis.toolbar
                            }, gis.route.southPanel]
                        }
                    ]
                }
             ]
    });
    
    gis.formMask = new Ext.LoadMask(
        gis.route.searchPanel.getEl(), {
            msg: globalLabels.waitMessage,
            store: gis.route.dataStore
        }
    );
    gis.formMask.show();
    
    gis.gridPanelMask = new Ext.LoadMask(
        gis.route.southPanel.getEl(), {
            msg: globalLabels.waitMessage
        }
    );
    gis.gridPanelMask.show();
    
    
    gis.poi.descriptionMask = new Ext.LoadMask(
        gis.poi.descriptionPanel.getEl(),{ //.body, { //getEl(), {
            msg: globalLabels.waitMessage
        }
    );
    gis.route.descriptionMask = new Ext.LoadMask(
        gis.route.descriptionPanel.getEl(),{ //.body, {
            msg: globalLabels.waitMessage
        }
    );
    
    gis.globalMask = new Ext.LoadMask(
        Ext.getBody(), {
            msg: globalLabels.waitMessage
        }
    );

    // Toolbar filling (see admin.js file when authenticated)
    gis.populateToolbar();
    // it will be shown only when needed (when route loads with POIs)
    gis.toolbar.disable();
    
    //gis.viewport.doLayout();
    
    // handling of notice for login/logout events
    var notice = Ext.get('notice');
    if (notice) {
        notice.fadeOut({
            duration: 5, 
            remove: true
        });
    }
};

