﻿// Oggetto con tutti i gestori della mappe utilizzate
var MapViewer = new MapViewerInstances();


/*
* Classe: MapViewerPoint
* Gestisce una istanza di punto sulla mapppa
*
* parPointKey -> Chiave (usata lato server) per identificare il punto
*/
function MapViewerPoint(parPointKey, parInstance)
{

    // Dichiarazione funzioni
    this.GetPointKey    = GetPointKey;
    this.GetMarker      = GetMarker;
    this.SetMarker      = SetMarker;
    this.GetInfoHTML    = GetInfoHTML;
    this.SetInfoHTML    = SetInfoHTML;
    this.ShowInfoWindow = ShowInfoWindow;
    this.Dispose        = Dispose;
    
    // Riferimento alll'oggetto che gestisce la mappa in cui il punto è contenuto
    this.pInstance = parInstance;
    
    // Chiave per identificare il punto
    this.pPointKey = parPointKey;
    
    // Oggetto GMarker
    this.pMarker = null;
    
    // HTML da visualizzare nella finestra del Marker
    this.pInfoHTML = '';
    
    // Listener per sentire il click sul Marker
    this.pListener = null;
    
        
    /*
    * Restituisce la chiave per identificare il punto
    */
    function GetPointKey()
    {
        return this.pPointKey;
    }
    
    /*
    * Restituisce l'oggetto Marker
    */
    function GetMarker()
    {
        return this.pMarker;
    }
    
    /*
    * Imposta l'oggetto Marker
    *
    * parMarker   -> oggetto Marker che rappresenta il punto sulla mappa
    * parInstance -> riferimento all'oggetto MapViewerInstance
    */
    function SetMarker(parMarker)
    {
        var thisPoint = this;
        var thisInstance = this.pInstance;
    
        // Deregistra il Listener all'evento di Click, se registrato
        if(this.pListener != null)
        {
            GEvent.removeListener(this.pListener);
            this.pListener = null;
        }
        
        // Toglie il vecchio marker dalla mappa, se presente
        if(this.pMarker != null)
            this.pInstance.GetMap().removeOverlay(this.pMarker);
        
        // Imposta il riferimento al nuovo marker
        this.pMarker = parMarker;
        
        // Aggiunge il marker alla mappa
        if(this.pMarker != null)
            this.pInstance.GetMap().addOverlay(this.pMarker);
        
        // Registra il Listener
        if(this.pMarker != null)
            this.pListener = GEvent.addListener(this.pMarker, "click", function() { thisInstance.ShowInfoWindow(thisPoint.GetPointKey()); } );
    }
    
    /*
    * Restituisce l'HTML da visualizzare nella finestra informativa associata al punto
    */
    function GetInfoHTML()
    {
        return this.pInfoHTML;
    }
    
    /*
    * Imposta l'HTML da visualizzare nella finestra informativa associata al punto
    */
    function SetInfoHTML(parInfoHTML)
    {
        this.pInfoHTML = parInfoHTML;
    }
        
    /*
    * Visualizza la finestra informativa (solo se è stato specificato l'HTML informativo).
    * Restituisce true se la finestra è stata aperta.
    */
    function ShowInfoWindow()
    {
        if((this.pMarker != null) && (this.pInfoHTML != ''))
        {
            this.pMarker.openInfoWindow(this.pInfoHTML);
            return true;
        }
        return false;
    }
    
    /*
    * Libera le risorse
    */
    function Dispose()
    {
        if(this.pInstance != null)
        {
            this.SetMarker(null);
            this.pPointKey = null;
            this.pInfoHTML = null;
            this.pInstance = null;
        }
    }
}


/*
* Classe: MapViewerInstance
* Gestisce una istanza di mappa
*
* parElementId -> Id del DIV che contiene la mappa
*/
function MapViewerInstance(parElementId)
{

    // Dichiarazione funzioni
    this.AttachEvent             = AttachEvent;
    this.OnUpdate                = OnUpdate;    
    this.GetElementId            = GetElementId;
    this.GetMap                  = GetMap;
    this.ShowGLargeMapControl    = ShowGLargeMapControl;
    this.ShowGSmallMapControl    = ShowGSmallMapControl;
    this.ShowGScaleControl       = ShowGScaleControl;
    this.ShowGSmallZoomControl   = ShowGSmallZoomControl;
    this.ShowGMapTypeControl     = ShowGMapTypeControl;
    this.ShowGOverviewMapControl = ShowGOverviewMapControl;
    this.InitializeMap           = InitializeMap;
    this.ResizeMap               = ResizeMap;
    this.GetPoint                = GetPoint;
    this.RemovePoint             = RemovePoint;
    this.ClearPoints             = ClearPoints;
    this.ShowInfoWindow          = ShowInfoWindow;
    this.SetPoint                = SetPoint;
    this.Dispose                 = Dispose;
    
    // Id del DIV che contiene la mappa
    this.pElementId = parElementId;
    
    // Variabile per disabilitare la chiamata del metodo OnUpdate lato server
    this.pUpdateDisabled      = false;
    
    // Riferimento alla GoogleMap
    this.pMap                 = new GMap2(document.getElementById(this.pElementId));
    
    // Riferimenti ai componenti aggiuntivi della mappa (se istanziati)
    this.pGLargeMapControl    = null;
    this.pGSmallMapControl    = null;
    this.pGScaleControl       = null;
    this.pGSmallZoomControl   = null;
    this.pGMapTypeControl     = null;
    this.pGOverviewMapControl = null;
    
    // Listener agli eventi generati dalla GoogleMap
    this.pListenerZoomEnd        = this.AttachEvent("zoomend");
    this.pListenerMoveEnd        = this.AttachEvent("moveend");
    this.pListenerMapTypeChanged = this.AttachEvent("maptypechanged");
    
    // Array di oggetti MapViewerPoint, con l'elenco dei punti evidenziati sulla mappa
    this.pPoints              = new Array();
    
            
    /*
    * Collega all'evento indicato dal parametro la funzione di onUpdate
    */
    function AttachEvent(parEventName)
    {
        var thisInstance = this;
        return GEvent.addListener(this.pMap, parEventName, function() { OnUpdate(thisInstance); } )
    }
    
    /*
    *  Invia un comando di update al server
    */
    function OnUpdate(parInstance)
    {
        var tValue;
            
        // Verifica che l'invio degli update lato server non sia temporaneamente disabilitato..
        if(!parInstance.pUpdateDisabled)
        {
            
            // Costruisce una stringa che descrive lo stato della mappa (parametri della funzione OnUpdate)
            tValue = '';
            
            // Latitudine del punto centrale
            tValue += parseFloat(parInstance.pMap.getCenter().lat()) +  "|;"
            
            // Longitudine del punto centrale
            tValue += parseFloat(parInstance.pMap.getCenter().lng()) +  "|;";
            
            // Livello di zoom
            tValue += parInstance.pMap.getZoom() +  "|;";
            
            // Tipo di mapppa
            if(parInstance.pMap.getCurrentMapType() == G_NORMAL_MAP)
                tValue += "N";
            else if(parInstance.pMap.getCurrentMapType() == G_SATELLITE_MAP)
                tValue += "S";
            else if(parInstance.pMap.getCurrentMapType() == G_DEFAULT_MAP_TYPES)
                tValue += "D";
            else if(parInstance.pMap.getCurrentMapType() == G_HYBRID_MAP)
                tValue += "H";
            else
                tValue += "N";            
            
            // Invia l'update lato server, tramite funzione SendCommand
            SendCommand(document.getElementById("SessionId").value, parInstance.pElementId, 1, 'OnUpdate', tValue);
        }        
    }        
    
    /*
    * Restituisce l'ElementId (cioè l'ID del DIV che contiene la mappa)
    */
    function GetElementId()
    {
        return this.pElementId;
    }
    
    /*
    * Restituisce l'oggetto Mappa
    */
    function GetMap()
    {
        return this.pMap;
    }    
    
    /*
    * Visualizza/nasconde il controllo completo per muoversi sulla mappa
    */ 
    function ShowGLargeMapControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGLargeMapControl == null)
            {
                this.pGLargeMapControl = new GLargeMapControl()
                this.pMap.addControl(this.pGLargeMapControl);
            }
        }
        else
        {
            if(this.pGLargeMapControl != null)
            {
                this.pMap.removeControl(this.pGLargeMapControl);
                this.pGLargeMapControl = null;
            }
        }
        
    }
    
    /*
    * Visualizza/nasconde il controllo ridotto per muoversi sulla mappa
    */
    function ShowGSmallMapControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGSmallMapControl == null)
            {
                this.pGSmallMapControl = new GSmallMapControl()
                this.pMap.addControl(this.pGSmallMapControl);
            }
        }
        else
        {
            if(this.pGSmallMapControl != null)
            {
                this.pMap.removeControl(this.pGSmallMapControl);
                this.pGSmallMapControl = null;
            }
        }
    }
    
    /*
    * Visualizza/nasconde il controllo per modificare la scala della mappa
    */
    function ShowGScaleControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGScaleControl == null)
            {
                this.pGScaleControl = new GScaleControl()
                this.pMap.addControl(this.pGScaleControl);
            }
        }
        else
        {
            if(this.pGScaleControl != null)
            {
                this.pMap.removeControl(this.pGScaleControl);
                this.pGScaleControl = null;
            }
        }
    }
    
    /*
    * Visualizza/nasconde il controllo per modificare lo zoom della mappa
    */
    function ShowGSmallZoomControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGSmallZoomControl == null)
            {
                this.pGSmallZoomControl = new GSmallZoomControl()
                this.pMap.addControl(this.pGSmallZoomControl);
            }
        }
        else
        {
            if(this.pGSmallZoomControl != null)
            {
                this.pMap.removeControl(this.pGSmallZoomControl);
                this.pGSmallZoomControl = null;
            }
        }
    }

    /*
    * Visualizza/nasconde il controllo per scegliere il tipo di mappa
    */
    function ShowGMapTypeControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGMapTypeControl == null)
            {
                this.pGMapTypeControl = new GMapTypeControl()
                this.pMap.addControl(this.pGMapTypeControl);
            }
        }
        else
        {
            if(this.pGMapTypeControl != null)
            {
                this.pMap.removeControl(this.pGMapTypeControl);
                this.pGMapTypeControl = null;
            }
        }
    }
    
    /*
    * Visualizza/nasconde il controllo con l'overview
    */
    function ShowGOverviewMapControl(parVisible)
    {        
        if(parVisible)
        {
            if(this.pGOverviewMapControl == null)
            {
                this.pGOverviewMapControl = new GOverviewMapControl()
                this.pMap.addControl(this.pGOverviewMapControl);
            }
        }
        else
        {
            if(this.pGOverviewMapControl != null)
            {
                this.pMap.removeControl(this.pGOverviewMapControl);
                this.pGOverviewMapControl = null;
            }
        }
    }
    
    /*
    * Inizializza la mappa a partire dalla stringa di configurazione ricevuta
    */
    function InitializeMap(parParameters)
    {
        var tParameters;                // Lista dei parametri di configurazione della mappa
        var iParameter;                 // Indice per scorrere i parametri di configurazione della mappa
        
        var tCenterLatitude;            // Latitudine del punto centrale della mappa
        var tCenterLongitude;           // Longitudine del punto centrale della mappa
        var tZoomLevel;                 // Livello di zoom
        var tMapType;                   // Tipo di mappa
        var tDisableDragging;           // Indica se disabilitare il dragging
        var tShowLargeMapControl;       // Indica se visualizzare il controllo di posizionamento estesto
        var tShowSmallMapControl;       // Indica se visualizzare il controllo di posizionamento ridotto
        var tShowScaleControl;          // Indica se visualizzare il controllo scala
        var tShowZoomControl;           // Indica se visualizzare il controllo zoom
        var tShowMapTypeControl;        // Indica se visualizzare il controllo tipo di mappa
        var tShowOverviewMapControl;    // Indica se visualizzare l'overview
        
        
        // Disabilita temporanemante l'invio degli update lato server
        this.pUpdateDisabled = true;
        
        // Separa i parametri ricevuti
        tParameters = parParameters.split('§');
        
        // Scorre tutti i parametri ricevuti
        for(iParameter = 0; iParameter < tParameters.length; ++iParameter)
        {            
            switch(iParameter)
            {
            
                // Latitudine del centro della mappa
                case 0:
                    tCenterLatitude = parseFloat(tParameters[iParameter]);
                    break;
                
                // Longitudine del centro della mappa
                case 1:
                    tCenterLongitude = parseFloat(tParameters[iParameter]);
                    break;
                
                // Livello di Zoom
                case 2:
                    tZoomLevel = parseInt(tParameters[iParameter]);
                    break;
                
                // Tipo di mappa
                case 3:
                    if(tParameters[iParameter] == 'N')
                        tMapType = G_NORMAL_MAP;
                    else if(tParameters[iParameter] == 'S')
                        tMapType = G_SATELLITE_MAP;
                    else if(tParameters[iParameter] == 'D')
                        tMapType = G_DEFAULT_MAP_TYPES;
                    else if(tParameters[iParameter] == 'H')
                        tMapType = G_HYBRID_MAP;
                    else
                        tMapType = G_NORMAL_MAP;
                    break;
                
                // Disabilitazione del dragging
                case 4:
                    tDisableDragging = (tParameters[iParameter] != '0');
                    break;
                    
                // Visualizzazione controllo di posizionamento estesto
                case 5:
                    tShowLargeMapControl = (tParameters[iParameter] != '0');
                    break;
                    
                // Visualizzazione controllo di posizionamento ridotto    
                case 6:
                    tShowSmallMapControl = (tParameters[iParameter] != '0');
                    break;
            
                // Visualizzazione controllo scala
                case 7:
                    tShowScaleControl = (tParameters[iParameter] != '0');
                    break;
                    
                // Visualizzazione controllo zoom
                case 8:
                    tShowZoomControl = (tParameters[iParameter] != '0');
                    break;
                
                // Visualizzazione tipo di mappa
                case 9:
                    tShowMapTypeControl = (tParameters[iParameter] != '0');
                    break;
                
                // Visualizzazione overview
                case 10:
                    tShowOverviewMapControl = (tParameters[iParameter] != '0');
                    break;                                
            }
        }
        
        this.pMap.checkResize();
                
        // Disabilita la possibilità di modificare lo Zoom tramite doppio click
        this.pMap.disableDoubleClickZoom();
        
        // Imposta il centro della mappa
        this.pMap.setCenter(new GLatLng(tCenterLatitude, tCenterLongitude), tZoomLevel);
        
        // Imposta il tipo di mappa
        this.pMap.setMapType(tMapType);
        
        // Disabilita il dragging
        if(tDisableDragging)
        {
            this.pMap.disableDragging();        
            this.pMap.disableScrollWheelZoom();
        }        
        else
        {
            this.pMap.enableDragging();
            this.pMap.enableScrollWheelZoom();
        }
                
        // Visualizza il controllo completo per muoversi sulla mappa
        this.ShowGLargeMapControl(tShowLargeMapControl);
        
        // Visualizza il controllo ridotto per muoversi sulla mappa    
        this.ShowGSmallMapControl(tShowSmallMapControl);
        
        // Visualizza il controllo per modificare la scala della mappa
        this.ShowGScaleControl(tShowScaleControl);
        
        // Visualizza il controllo per modificare lo zoom della mappa
        this.ShowGSmallZoomControl(tShowZoomControl);
        
        // Visualizza il controllo per scegliere il tipo di mappa    
        this.ShowGMapTypeControl(tShowMapTypeControl);
        
        // Visualizza il controllo con l'Overview
        this.ShowGOverviewMapControl(tShowOverviewMapControl);
        
        // Riabilita l'invio degli update lato server
        this.pUpdateDisabled = false;
    }    
    
    /*
    * Forza un refresh delle dimensioni della mappa
    */
    function ResizeMap(parParameters)
    {
        this.pMap.checkResize();
        this.OnUpdate(this);
    }    
    
    /*
    * Cerca l'oggetto che gestisce il punto con la chiave specificata.
    * 
    * parPointKey          -> Chiave del punto da cercare
    * parCreateIfNotExists -> Indica se creare l'oggetto, qualora non esista ancora
    */
    function GetPoint(parPointKey, parCreateIfNotExists)
    {
        var iPoint        = 0;
        var tPoint        = null;        
        
        // Cerca l'oggetto che gestisce il punto con la chiave specificata..
        for(iPoint = 0; iPoint < this.pPoints.length; ++iPoint)
        {
            if(this.pPoints[iPoint].GetPointKey() == parPointKey)
            {
                tPoint = this.pPoints[iPoint];                
                break;
            }
        }
        
        // Se l'oggetto cercato non è stato trovato e deve essere istanziato..
        if((tPoint == null) && (parCreateIfNotExists))
        {
            // .. lo istanzia 
            tPoint = new MapViewerPoint(parPointKey, this);
            
            // .. e lo aggiunge all'array
            this.pPoints[this.pPoints.length] = tPoint;
        }
        
        // Restituisce il riferimento all'oggetto trovato
        return tPoint;
    }
    
    /*
    * Rimuove il punto con la chiave specificata
    *
    * parPointKey -> Chiave del punto da rimuovere
    */
    function RemovePoint(parPointKey)
    {
        var iPoint;
                
        // Cerca l'oggetto che gestisce il punto da rimuovere
        for(iPoint = 0; iPoint < this.pPoints.length; ++iPoint)
        {
            // Se ha trovato l'oggetto da rimuovere..
            if(this.pPoints[iPoint].GetPointKey() == parPointKey)
            {
                // .. ne effettua la dispose
                this.pPoints[iPoint].Dispose();
                
                // .. e lo toglie dall'Array
                this.pPoints.splice(iPoint, 1);
                                
                break;
            }
        }
    }
    
    /*
    * Rimuove tutti i punti
    */
    function ClearPoints()
    {
        var iPoint;
        
        // Effettua la dispose di tutti i punti
        for(iPoint = 0; iPoint < this.pPoints.length; ++iPoint)
            this.pPoints[iPoint].Dispose();
        
        // Svuota l'Array    
        this.pPoints.splice(0, this.pPoints.length);
    }
    
    /*
    * Visualizza la finestra informativa relativa al punto specificato
    */
    function ShowInfoWindow(parPointKey)
    {
        var tPoint;
        
        // Cerca il punto
        tPoint = this.GetPoint(parPointKey, false);                
        if(tPoint != null)
        {
            // Visualizza la finestra informativa
            if(!tPoint.ShowInfoWindow())
                this.pMap.closeInfoWindow();
            
            // Libera le risorse
            tPoint = null;
        }
    }
    
    /*
    * Inizializza il punto con la chiave specificata a partire dalla stringa di configurazione ricevuta
    */
    function SetPoint(parParameters)
    {
        var tParameters;                // Lista dei parametri di configurazione del punto
        var iParameter;                 // Indice per scorrere i parametri di configurazione del punto
                
        var tPointKey;                  // Chiave del punto da inizializzare
        var tLatitude;                  // Latitudine del punto
        var tLongitude;                 // Longitudine del punto
        var tIconPath;                  // Path dell'icona              ("" = icona di default)
        var tIconWidth;                 // Larghezza dell'icona         (-1 = non specificata)
        var tIconHeight;                // Altezza dell'icona           (-1 = non specificata)
        var tIconAnchorX;               // Ancoraggio X dell'icona      (-1 = non specificato)
        var tIconAnchorY;               // Ancoraggio Y dell'icona      (-1 = non specificato)
        var tShadowPath;                // Path dell'icona ombra        ("" = icona di default)
        var tShadowWidth;               // Larghezza dell'icona ombra   (-1 = non specificata)
        var tShadowHeight;              // Altezza dell'icona ombra     (-1 = non specificata)
        var tInfoHTML = '';             // Messaggio informativo
        
        var tIcon   = null;        
        var tMarker = null;
        var tPoint  = null;
                
                
        // Separa i parametri ricevuti
        tParameters = parParameters.split('§');
        
        // Scorre tutti i parametri ricevuti
        for(iParameter = 0; iParameter < tParameters.length; ++iParameter)
        {            
            switch(iParameter)
            {
            
                // Chiave del punto
                case 0:
                    tPointKey = tParameters[iParameter];
                    break;
            
                // Latitudine del punto
                case 1:
                    tLatitude = parseFloat(tParameters[iParameter]);
                    break;
                
                // Longitudine del punto
                case 2:
                    tLongitude = parseFloat(tParameters[iParameter]);
                    break;
                
                // Path dell'icona
                case 3:
                    tIconPath = tParameters[iParameter];
                    break;
                    
                // Larghezza dell'icona
                case 4:
                    tIconWidth = parseInt(tParameters[iParameter]);
                    break;
                    
                // Altezza dell'icona
                case 5:
                    tIconHeight = parseInt(tParameters[iParameter]);
                    break;
                    
                // Ancoraggio X dell'icona
                case 6:
                    tIconAnchorX = parseInt(tParameters[iParameter]);
                    break;
                    
                // Ancoraggio Y dell'icona
                case 7:
                    tIconAnchorY = parseInt(tParameters[iParameter]);
                    break;
                    
               // Path dell'icona ombra
                case 8:
                    tShadowPath = tParameters[iParameter];
                    break;
                    
                // Larghezza dell'icona ombra
                case 9:
                    tShadowWidth = parseInt(tParameters[iParameter]);
                    break;
                    
                // Altezza dell'icona ombra
                case 10:
                    tShadowHeight = parseInt(tParameters[iParameter]);
                    break;
                    
                // Messaggio informativo
                case 11:
                    tInfoHTML = tParameters[iParameter];
                    break;
            }
        }
                
        // Istanzia l'icona        
        tIcon = new GIcon(G_DEFAULT_ICON);
        
        // Se è specificato un path per l'icona..
        if(tIconPath != '')
        {
            // .. imposta il path dell'icona
            tIcon.image = tIconPath;
            
            // .. imposta le dimensioni dell'icona
            if((tIconWidth >= 0) && (tIconHeight >= 0))
                tIcon.iconSize = new GSize(tIconWidth, tIconHeight);
                
            // .. imposta l'ancoraggio dell'icona
            if((tIconAnchorX >= 0) && (tIconAnchorY >= 0))
                tIcon.iconAnchor = new GPoint(tIconAnchorX, tIconAnchorY);
        }
        
        // Se è specificato un path per l'icona ombra..
        if(tShadowPath != '')
        {
            // .. imposta il path dell'icona ombra
            tIcon.shadow = tShadowPath;
            
            // .. imposta le dimensioni dell'icona ombra
            if((tShadowWidth >= 0) && (tShadowHeight >= 0))
                tIcon.shadowSize = new GSize(tShadowWidth, tShadowHeight);
        }
        
                
        // Crea il nuovo marker
        tMarker = new GMarker(new GLatLng(tLatitude, tLongitude), { icon: tIcon });        
        
        // Cerca e inizializza l'oggetto che gestisce il punto
        tPoint = this.GetPoint(tPointKey, true);
        tPoint.SetMarker(tMarker);
        tPoint.SetInfoHTML(tInfoHTML);
        
        // Libera le risorse
        tPoint = null;
        tMarker = null;
        tIcon = null;
    }
    
    /*
    * Libera le risorse
    */
    function Dispose()
    {
        if(this.pMap != null)
        {
            this.pUpdateDisabled = true;
            
            // Elimina tutti i punti evidenziati
            this.ClearPoints();
            
            // Si sgancia dagli eventi
            GEvent.removeListener(this.pListenerZoomEnd);
            GEvent.removeListener(this.pListenerMoveEnd);
            GEvent.removeListener(this.pListenerMapTypeChanged);
            
            // Libera le risorse
            this.pListenerZoomEnd = null;
            this.pListenerMoveEnd = null;
            this.pListenerMapTypeChanged = null;                        
            
            this.pGLargeMapControl    = null;
            this.pGSmallMapControl    = null;
            this.pGScaleControl       = null;
            this.pGSmallZoomControl   = null;
            this.pGMapTypeControl     = null;
            this.pGOverviewMapControl = null;
            
            this.pPoints = null;
            this.pMap = null;
        }
    }
}


/*
* Classe: MapViewerInstances
* Gestisce l'array con tutte le istanze di mappa
*/
function MapViewerInstances()
{
    // Definizione delle funzioni
    this.GetGoogleApiAvailable = GetGoogleApiAvailable;
    this.GetInstance           = GetInstance;
    this.RemoveInstance        = RemoveInstance;
    this.ClearInstances        = ClearInstances;
    this.ExecuteCommand        = ExecuteCommand;
    this.Dispose               = Dispose;
    
    // Array delle istanze
    this.pInstances = new Array();
    
    // Indica se le GoogleAPI sono disponibili
    this.pGoogleAPIAvailable = false;
    this.pGoogleAPIAvailableValid = false;
    
    
    /*
    * Restituisce true se le API di GoogleMaps sono disponibili
    */
    function GetGoogleApiAvailable()
    {
        var tOk;
    
        if(!this.pGoogleAPIAvailableValid)
        {
    
            // Verifica che l'API di GoogleMaps sia stata caricata
            this.pGoogleAPIAvailable = GoogleMapsAPILoaded;

            // Verifica che il browser in uso sia compatibile con l'API di GoogleMaps
            if(this.pGoogleAPIAvailable)
                this.pGoogleAPIAvailable = GBrowserIsCompatible();
        }
        
        // Restituisce true se le API di GoogleMaps sono disponibili
        return this.pGoogleAPIAvailable;
    }
    
    /*
    * Cerca l'oggetto che gestisce la mappa associata al DIV con l'ID specificato.
    * Se tale oggetto non esiste ancora, lo istanzia.
    */
    function GetInstance(parElementId, parCreateIfNotExists)
    {
        var iInstance      = 0;
        var tInstance      = null;
        
        // Cerca l'oggetto che gestisce la mappa associata al DIV con l'ID specificato..
        for(iInstance = 0; iInstance < this.pInstances.length; ++iInstance)
        {
            if(this.pInstances[iInstance].GetElementId() == parElementId)
            {            
                tInstance = this.pInstances[iInstance];
                break;
            }
        }
        
        // Se l'oggetto cercato non è stato trovato e deve essere creato..
        if((tInstance == null) && (parCreateIfNotExists))
        {
            // .. lo istanzia
            tInstance = new MapViewerInstance(parElementId);
            
            // .. e lo aggiunge all'array
            this.pInstances[this.pInstances.length] = tInstance;
        }
        
        // Restituisce il riferimento all'oggetto che gestisce la mappa cercata
        return tInstance;
    }
    
    /*
    * Rimuove l'oggeto che gestisce la mappa associata al DIV specificato
    */
    function RemoveInstance(parElementId)
    {
        var iInstance;
                
        // Cerca l'oggetto che gestisce la mappa da rimuovere
        for(iInstance = 0; iInstance < this.pInstances.length; ++iInstance)
        {
            // Se ha trovato l'oggetto da rimuovere..
            if(this.pInstances[iInstance].GetElementId() == parElementId)
            {
                // .. ne effettua la dispose
                this.pInstances[iInstance].Dispose();
                
                // .. e lo toglie dall'Array
                this.pInstances.splice(iInstance, 1);
                
                break;
            }
        }
    }
    
    /*
    * Rimuove tutte le istanze di mappa
    */
    function ClearInstances()
    {
        var iInstance;
        
        // Effettua la dispose di tutti le istanze
        for(iInstance = 0; iInstance < this.pInstances.length; ++iInstance)
            this.pInstances[iInstance].Dispose();
        
        // Svuota l'Array
        this.pInstances.splice(0, this.pInstances.length);
    }
    
    /*
    * Esegue un comando proveniente dal server.
    * La stringa di configurazione ricevuta è costituita da gruppi di parametri, nella forma:
    *     COMANDO#parametri#COMANDO#parametri...    
    */
    function ExecuteCommand(parElementId, parParameters)
    {
        var tParametersGroups;          // Lista di gruppi di parametri (il primo descrive la configurazione della mappa, i successivi descrivono i punti da visualizzare)
        var iParametersGroup;           // Indice per scorrere i gruppi di parametri
        var tInstance = null;           // Istanza della mappa su cui eseguire i comandi
        
                
        if(MapViewer.GetGoogleApiAvailable())
        {            
            
            // Separa i gruppi di parametri ricevuti
            tParametersGroups = parParameters.split('#');
            
            // Scorre tutti i gruppi di parametri individuati
            for(iParametersGroup = 0; iParametersGroup < tParametersGroups.length; iParametersGroup += 2)
            {
                
                // Verifica che il DIV in cui inserire la mappa sia già stato inserito nella pagina
                if((document.getElementById(parElementId) == null) && (tParametersGroups[iParametersGroup] != 'DISPOSE'))
                    return;
        
                switch(tParametersGroups[iParametersGroup])
                {
                
                    // Impostazione della configurazione di base della mappa
                    case 'MAPINIT':         /* parametri di configurazione della mappa */
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.InitializeMap(tParametersGroups[iParametersGroup + 1]);
                        break;
                        
                    // Ridimensionamento della mappa
                    case 'MAPRESIZE':
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.ResizeMap();
                        break;
                    
                    // Impostazione di un punto evidenziato sulla mappa
                    case 'POINTSET':        /* parametri di configurazione del punto */
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.SetPoint(tParametersGroups[iParametersGroup + 1]);
                        break;
                        
                    // Rimozione di un punto evidenziato sulla mappa
                    case 'POINTREMOVE':     /* key del punto */
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.RemovePoint(tParametersGroups[iParametersGroup + 1]);
                        break;
                        
                    // Rimozione di tutti i punti dalla mappa
                    case 'POINTSCLEAR':
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.ClearPoints();
                        break;
                    
                    // Apertura di una finestra informativa
                    case 'SHOWINFO':
                        if(tInstance == null) tInstance = this.GetInstance(parElementId, true);
                        tInstance.ShowInfoWindow(tParametersGroups[iParametersGroup + 1]);
                        break;
                        
                    // Dispose di una mappa
                    case 'DISPOSE':
                        this.RemoveInstance(parElementId);
                        break;
                }
            }
        }
    }
    
    /*
    * Libera le risorse
    */
    function Dispose()
    {
        if(this.pInstances != null)
        {
            
            // Elimina tutte le istanze di mappa
            this.ClearInstances();
            
            // Libera le risorse
            this.pInstances = null;           
        }
    }    
}

