﻿/* CONSTANTS */

/* services */
var GOOGLE_MAPS = '1';
var YAHOO_MAPS = '2';
var LIVESEARCH_MAPS = '3';

/* zoom levels */
var COUNTRY_ZOOM = 1;
var STATE_ZOOM = 2;
var CITY_ZOOM = 3;
var STREET_ZOOM = 4;

var centerPointCallbackFunction = null;
    
/* ******************************** GEOMAPPING **************************************/

// Constructs new geomapping object
function Geomapping(serviceName, mapContainerId)
{
    if(document.getElementById(mapContainerId) == null)
       return null;
    
    this._serviceName = serviceName;
    this._mapContainerId = mapContainerId;
    this._map = null;
    this._centerPointCallbackFunction = null;
}

// loads map into a map container
Geomapping.prototype.LoadMap = function(onLoadCallbackFunction)
{
    this.UnloadMap();
    switch(this._serviceName)
    {
        case GOOGLE_MAPS:
            this._map = new GMap2(document.getElementById(this._mapContainerId));
            break;
        case YAHOO_MAPS:
            this._map = new YMap(document.getElementById(this._mapContainerId), YAHOO_MAP_REG);
            break;
        case LIVESEARCH_MAPS:
            this._map = new VEMap(this._mapContainerId);
            this._map.LoadMap();
            break;
    }
}

// unloads the map
Geomapping.prototype.UnloadMap = function()
{
  this._map = null;
  var ctrl = document.getElementById(this._mapContainerId);
  if(ctrl != null)
  {
    while (ctrl.childNodes[0])
    {
        ctrl.removeChild(ctrl.childNodes[0]);
    }
  }
}

// shows map in a designated container
Geomapping.prototype.ShowMap = function(geoPoint, zoom, showLocationPin, allowDragging)
{
    if(zoom == null)
    {
        zoom = STREET_ZOOM;
    }
    if(showLocationPin == null)
    {
        showLocationPin = true;
    }
    if(allowDragging == null)
    {
        allowDragging = false;
    }
    
    this.LoadMap();
    this.ShowMapInternal(this._serviceName, geoPoint.Lat, geoPoint.Lon, zoom, showLocationPin, allowDragging);
}

// acquires geo longitude and geo latitude of the center point of the map
Geomapping.prototype.AcquireCenterPoint = function(street, city, country, state, callbackFunction)
{
    centerPointCallbackFunction = callbackFunction;
    var query = GetPlaceQuery(this._serviceName, street, city, country, state);
    
    this.LoadMap();
    this.AcquireCenterPointInternal(this._serviceName, "'" + query + "'");
}

/* ******************************** INTERNAL FUNCTIONS ************************** */
Geomapping.prototype.ShowMapInternal = function(_serviceName, lat, lon, zoom, showLocationPin, allowDragging)
{
    var geoPoint = new GeoPoint(lon, lat);

    switch(_serviceName)
        {
            case GOOGLE_MAPS:
                this._map.setCenter(new GLatLng(geoPoint.Lat, geoPoint.Lon), GetZoomValue(zoom, _serviceName));
                if(showLocationPin)
                    this._map.addOverlay(new GMarker(new GLatLng(geoPoint.Lat, geoPoint.Lon)));
                if(!allowDragging)
                    this._map.disableDragging();
            break;
        case YAHOO_MAPS:
            this._map.drawZoomAndCenter(new YGeoPoint(geoPoint.Lat, geoPoint.Lon), GetZoomValue(zoom, _serviceName));
            if(showLocationPin)
                this._map.addMarker(new YGeoPoint(geoPoint.Lat, geoPoint.Lon));
            if(allowDragging)
                this._map.enableDragMap();
            else
                this._map.disableDragMap();
            break;
        case LIVESEARCH_MAPS:
            this._map.LoadMap(new VELatLong(geoPoint.Lat, geoPoint.Lon), GetZoomValue(zoom, _serviceName), 'r', !allowDragging);
            this._map.HideDashboard();
            if(showLocationPin)
            {
                var shape = new VEShape(VEShapeType.Pushpin, this._map.GetCenter());
                this._map.AddShape(shape);
            }
            this._map.Resize();
            break;
    }
}

Geomapping.prototype.AcquireCenterPointInternal = function(_serviceName, query)
{
    switch(_serviceName)
    {
        case GOOGLE_MAPS:
            geocoder = new GClientGeocoder();    
            geocoder.getLocations(query, this.AcquireCenterPointGoogle_Callback);
            break;
        case YAHOO_MAPS:
            this._map.drawZoomAndCenter(query, 12); // the zome value here is not important
            YEvent.Capture(this._map, EventsList.endMapDraw, this.AcquireCenterPointYahoo_Callback);
            break;
        case LIVESEARCH_MAPS:
            this._map.Find(null, query, null, null, 0, 1, true, true, false, true, this.AcquireCenterPointLiveSearch_Callback);
            break;
    }
}

Geomapping.prototype.AcquireCenterPointGoogle_Callback = function(response)
{
    if(!response || response.Status.code != 200)
    {
        // TODO: implement localizable error handling here
        alert('Sorry this location could not be geomapped!');
    }
    else
    {
        var place = response.Placemark[0];
        centerPointCallbackFunction(new GeoPoint(place.Point.coordinates[0], place.Point.coordinates[1]));
    }
}

Geomapping.prototype.AcquireCenterPointYahoo_Callback = function(_e)
{
   centerPointCallbackFunction(new GeoPoint(_e.YGeoPoint.Lon, _e.YGeoPoint.Lat));
}

Geomapping.prototype.AcquireCenterPointLiveSearch_Callback = function(layer, resultsArray, places, hasMore, veErrorMessage)
{
    if(veErrorMessage != null)
    {
        alert(veErrorMessage);
    }
    else
    {
        centerPointCallbackFunction(new GeoPoint(places[0].LatLong.Longitude, places[0].LatLong.Latitude));        
    }
}

/* ******************************** HELPER FUNCTION ***************************** */

// this function takes sitefinity zoom value and return appropriate zoom value for given service
function GetZoomValue(zoom, _serviceName)
{
    var zoomValue = '';
    switch(_serviceName)
    {
        case GOOGLE_MAPS:
            switch(zoom)
            {
                case COUNTRY_ZOOM:
                    zoomValue = 5;
                    break;
                case STATE_ZOOM:
                    zoomValue = 10;
                    break;
                case CITY_ZOOM:
                    zoomValue = 14;
                    break;
                case STREET_ZOOM:
                    zoomValue = 15;
                    break;
            }
            break;
        case YAHOO_MAPS:
            switch(zoom)
            {
                case COUNTRY_ZOOM:
                    zoomValue = 14;
                    break;
                case STATE_ZOOM:
                    zoomValue = 11;
                    break;
                case CITY_ZOOM:
                    zoomValue = 5;
                    break;
                case STREET_ZOOM:
                    zoomValue = 3;
                    break;
            }
            break;
        case LIVESEARCH_MAPS:
            switch(zoom)
            {
                case COUNTRY_ZOOM:
                    zoomValue = 5;
                    break;
                case STATE_ZOOM:
                    zoomValue = 8;
                    break;
                case CITY_ZOOM:
                    zoomValue = 12;
                    break;
                case STREET_ZOOM:
                    zoomValue = 15;
                    break;
            }
            break;
    }
    return zoomValue;
}

// this function takes location info from sitefinity and returns 
// a proper location query for given service
function GetPlaceQuery(_serviceName, street, city, country, state)
{
    var query = '';
    switch(_serviceName)
    {
        case GOOGLE_MAPS:
            query = street + ', ' + city + ', ' + country + ', ' + state;
            break;
        case YAHOO_MAPS:
            if(country.toUpperCase() == "UNITED STATES")
            {
                query = street + ', ' + city + ', ' + state;
            }
            else
            {
                query = street + ', ' + city + ', ' + country;
            }
            break;
        case LIVESEARCH_MAPS:
            query = street + ', ' + city + ', ' + country + ', ' + state;
            break;
    }
    return query;
}

/* ******************************** OBJECTS ************************************* */

/* Geomapping point object */
function GeoPoint(longitude, latitude)
{
    this.Lon = longitude;
    this.Lat = latitude;
}