
/**
 *
 */
function BxMap (e, ed, et, ecity, ezip, elat, elon, ezoom, emaptype, eform)
{
    this._eCountry = e;        
    this._eDisplay = ed;        
    this._eText = et;
    this._eCity = ecity    
    this._eZip = ezip
    this._eLat = elat;
    this._eLon = elon;
    this._eZoom = ezoom;
    this._eMapType = emaptype;
    this._eForm = eform;

    this._map = null;
    this._geocoder = null;

    this._sCountryName = '';
    this._sCountryCode = '';
    this._sCountryCodeNew = '';
    this._iCountryId = '';
    this._sAddress = '';
    this._sCity = '';
    this._sZip = '';    

    this._fZoom = 0;
    this._point = null;

    this._locations = [];
}

/**
 * show the window with a map
 */
BxMap.prototype.show = function (sZip, sCity)
{
    if (this.isMapOpened()) return; 

    this._sCountryName = this.getCountryName();
    this._iCountryId = this.getCountryId();

    if (!GBrowserIsCompatible()) 
    {
        alert ('Please upgrade your browser.');
        return true;
    }

    $this = this;

    var w = new BxWnd (aBxConfig['urlRoot'] + 'GoogleMaps/xml_wnd_map/?c=' + this._iCountryId, aBxConfig['urlRoot'] + 'modules/GoogleMaps/layout/default/xsl/wnd_map.xsl');

    w.onClose = function ()
    {
        delete $this._geocoder;
        delete $this._map;
        $this._geocoder = null;
        $this._map = null;

        if (sCity)
        {
            $this._eForm.submit();
        }
    }

    w.setSize (820,400);    

    w.onLoadComplete = function ()
    {
        $this._map = new GMap2($("gmap"));

        $this._map.addControl(new GLargeMapControl());
        $this._map.addControl(new GMapTypeControl());
        $this._map.enableDoubleClickZoom ();
        $this._map.enableContinuousZoom ();

        $this.initMapClicks ();
        $this.showDefaultLocation ();
        $this._sCountryCode = $('country_code').innerHTML;
        $this._fZoom = parseInt($('f_zoom').innerHTML);
        if (sZip)
        {
            $('loc').value = sZip;
            if (sCity)
            {
                var h = function ()
                {
                    $('loc').value = sCity;
                    $this.suggest();
                }
                $this.suggest(h);
            }
            else
            {
                $this.suggest();
            }
        }
        else
        {
            $this.showCurrentCountry ($this._fZoom);
        }
    }
    w.show ('Select Your Location');        

    return false;           
}

/**
 * get selected country name
 */
BxMap.prototype.getCountryName = function ()
{
    var i = this._eCountry.selectedIndex;
    return this._eCountry.options[i].text;
}

/**
 * get selected country id
 */
BxMap.prototype.getCountryId = function ()
{    
    return this._eCountry.value;
}

/**
 * show zoomed country on the map
 */
BxMap.prototype.showCurrentCountry = function (fZoom)
{
    if ( this._eLat.value != 0 || this._eLon.value != 0)
    {
        this._fZoom = parseInt(this._eZoom.value);
        var point = new GLatLng(this._eLat.value, this._eLon.value);

        this.addmarker (point);
        this.saveAddress (this._eText.value, this._eCity.value, this._fZoom, '', this._eLat.value, this._eLon.value);        

        this._map.setCenter (point, this._fZoom);        

        if (this._eMapType.value.length && this._eMapType.value != this._map.getCurrentMapType().getName())
        {
            var a = this._map.getMapTypes();
            for ( var i = 0 ; i < a.length ; ++i )
            {
                if (this._eMapType.value == a[i].getName())
                {
                    this._map.setMapType(a[i]);
                    break;
                }
            }
        }
    

        return;
    }   

    if (!this._sCountryName.length)
    {
        this.showDefaultLocation ();
        return;
    }   

    if (!this._geocoder)
    {
        this._geocoder = new GClientGeocoder();        
    }

    this._geocoder.setBaseCountryCode (this._sCountryCode);        

    var $this = this;
    var h = function (r)
    {        
        if (!r || r.Status.code != 200) 
        {
            alert("Sorry, we were unable to geocode that address");
        } 
        else 
        {
            var place = r.Placemark[0];            
            var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);            
            $this._map.setCenter (point, fZoom);

            //$this.saveAddress (place.address, point.x, point.y);
        }
    }

    if (this._sCountryCode != 'GB' && this._sCountryCode != 'CH')
        this._geocoder.getLocations(this._sCountryName, h);
}

/**
 * sample search results
 */
BxMap.prototype.sample = function (sSample)
{
    $('loc').value = sSample;
    this.suggest();
}

/**
 * suggest address locations
 */
BxMap.prototype.suggest = function (funcNotfound)
{
    var sText = $('loc').value;

    if (!sText.length) return;

    if (!this._geocoder)
    {
        this._geocoder = new GClientGeocoder();        
    }

    this._geocoder.setBaseCountryCode (this._sCountryCode);

    var $this = this;

    var h = function (r)
    {        
        
        if (603 == r.Status.code) 
        {
            return;
        }


        if (!r || r.Status.code != 200) 
        {
            if (funcNotfound)
                funcNotfound();
            else
                alert("Sorry, we were unable to geocode that address");
        } 
        else 
        {            
            $this.resetLocations ();

            for (var i=0 ; i<r.Placemark.length ; ++i)
            {                
                var place = r.Placemark[i];
                var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
                
                var address = $this.genAddress (place.AddressDetails);

                $this.addLocation (address.str, address.city, address.zip, address.country, point, parseInt(place.AddressDetails.Accuracy));
            }

            $this.displayLocations ();

            if (1 == r.Placemark.length)
                $this.selectLocation (0);
        }
    }
    
    if ('GB' == this._sCountryCode || 'CH' == this._sCountryCode)
        this.getLocations(sText, h); 
    else
        this._geocoder.getLocations(sText, h); 

    return false;
}

/**
 * calc zoom by accuracy of address
 */
BxMap.prototype.calcZoom = function (iAccuracy)
{
    switch (iAccuracy)
    {
        case 3: // subregion
            return this._fZoom > 5 ? this._fZoom : 5;
        case 4: // city
            return this._fZoom > 6 ? this._fZoom : 6; // 12
        case 5: // postcode
            return this._fZoom > 8 ? this._fZoom : 8; // 14
        case 6: // street
            return this._fZoom > 8 ? this._fZoom : 8; // 15
        case 7: // intersection level
        case 8: // address level
            return 16;
        default: // country, region
            return this._fZoom;
    }
}

/**
 * show default location, the world
 */
BxMap.prototype.showDefaultLocation = function ()
{
    this._map.setCenter (new GLatLng(34, 0), 2);
}

/**
 * check if map window is opened
 */
BxMap.prototype.isMapOpened = function ()
{
    return $('gmap');
}

/**
 * initialize clicks on the map
 */
BxMap.prototype.initMapClicks = function ()
{
    var $this = this;

    var h = function (overlay, point)
    {
        $this.addmarker (point);
    }

    GEvent.addListener(this._map, "click", h);
}

/**
 * add location to the list of suggested locations
 */
BxMap.prototype.addLocation = function (sText, sCity, sZip, sCountryCode, point, acc)
{
    this._locations[this._locations.length] = { text: sText, city: sCity, zip: sZip, country: sCountryCode, point: point, acc: acc };
}

/**
 * clear list of suggested locations
 */
BxMap.prototype.resetLocations = function ()
{
    this._locations = [];
}

/**
 * display list of suggsted locations in the list box
 */
BxMap.prototype.displayLocations = function ()
{
    var sHtml = '<ul>';
    for ( var i=0 ; i < this._locations.length ; ++i )
    {
        sHtml += '<li><a href="javascript:void(0);" onclick="gBxMap.selectLocation(' + i + ')">' + this._locations[i].text + '</a></li>';
    }
    sHtml += '</ul>';

    $('glist').innerHTML = sHtml;
}

/**
 * display specified location on the map
 */
BxMap.prototype.selectLocation = function (i)
{
    var oLoc = this._locations[i];
 
    var fZoom = this.calcZoom (oLoc.acc);

    if ( oLoc.acc >= 4 ) // city and more accuracy
    {        
        this.addmarker (oLoc.point);
        this.saveAddress (oLoc.text, oLoc.city, oLoc.zip, oLoc.country, oLoc.point.x, oLoc.point.y);
    }    

    this._map.setCenter (oLoc.point, fZoom);
}


/**
 * add location marker on the map
 */
BxMap.prototype.addmarker = function (point)
{
    this._map.clearOverlays();

    this._point = point;

    var marker = new GMarker(point);
    this._map.addOverlay(marker);

    $('sel_btn').disabled = false;
}

/**
 * save address
 */
BxMap.prototype.saveAddress = function (s, city, zip, country, lat, lon)
{
    this._sAddress = s;
    this._sCity = city;
    this._sZip = zip;
    this._sCountryCodeNew = country;

    $('sel_loc').innerHTML = s;
    $('sel_coord').innerHTML = lat + ', ' + lon;
}

/**
* final selection
 */
BxMap.prototype.finalSelection = function ()
{
    if (!this._sAddress || !this._point.x || !this._point.y) 
    {
        alert ('You should find your or nearest city via the search box.');
        return false;
    }

    if (this._eDisplay) this._eDisplay.innerHTML = this._sAddress;
    this._eText.value = this._sAddress;
    this._eCity.value = this._sCity;
    this._eZip.value = this._sZip;
    this._eLon.value = this._point.x;
    this._eLat.value = this._point.y;
    this._eZoom.value = this._map.getZoom();
    this._eMapType.value = this._map.getCurrentMapType().getName();

    if (this._sCountryCodeNew.length && this._sCountryCodeNew != this._sCountryCode)
    {
        $('sel_btn').disabled = true;
        var $this = this;
        var h = function (id, status)
        {
            id = parseInt(id);
            if (id > 0)
            {
                $this._eCountry.value = id;
            }
            hideHTML();
        }
        GDownloadUrl (aBxConfig['urlRoot'] + 'join/get_country_id/?str_code='+this._sCountryCodeNew, h); 
    }
    else
    {
        hideHTML();
    }

    return false;
}

BxMap.prototype.getLocations = function (sText, h)
{
    var $this = this;       
    var hh = function (r)
    {
        h (eval('(' + r.responseText + ')'));
    }
    new BxXmlRequest (aBxConfig['urlRoot'] + 'GoogleMaps/json_geocode/?q=' + sText, hh, true);
}

BxMap.prototype.genAddress = function (o)
{
    var o = o.Country;    
    var zip = '';
    var address = o.CountryNameCode;
    var country = o.CountryNameCode;
    var city = '';

    if (o.AdministrativeArea)
    {
        o = o.AdministrativeArea;
        address = o.AdministrativeAreaName + ', ' + address;
    }
    if (o.SubAdministrativeArea)
    {
        o = o.SubAdministrativeArea;
        address = o.SubAdministrativeAreaName + ', ' + address;
    }

    if (o.Locality)
    {
        o = o.Locality;
        address = o.LocalityName + ', ' + address;
        zip = o.PostalCode ? o.PostalCode.PostalCodeNumber : '';
        city = o.LocalityName;
    }

    if (o.PostalCode)
    {
        zip = o.PostalCode.PostalCodeNumber;
    }
/*
    else
    if (o.DependentLocality)
    {
        o = o.DependentLocality;
        //address = o.DependentLocalityName + ', ' + address;
        //zip = o.PostalCode ? o.PostalCode.PostalCodeNumber : '';
        city = o.LocalityName;
    }
*/
    return { str: address, zip: zip, city: city, country: country };
}

BxMap.prototype._dump = function (o)
{
    var s = '';
    for (var i in o) s += i + " = " + o[i] + "\n";
    //for (var i in o) s += i + "\n";
    alert(s);
}



