// Geocoder Javascript for NetHotels AG
// Author Thomas Soldan
// Enjoy the amazing power of Google Maps :)

//================================================ Temopraliy BEGIN

//================================================ Temopraliy END


//================================================ Variables BEGIN
var i = 0;
var j = 0;
var geoMap = null;
var geoMarkers = null;
var geoCoder = null;
var geoInfoWindow = null;
var geoShadow = null;
var geoClickIcon = null;
var geoClickMarker = null;
var initialized = false;
var boundsOverlay = null;
var hashFragment = "";
var groupZip = null;
var domain = "";

var MAPFILES_URL = "http://maps.gstatic.com/intl/en_us/mapfiles/";

// Status messages from Google Maps
var GeocoderStatusDescription = {
    "OK": "The request did not encounter any errors",
    "UNKNOWN_ERROR": "A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known",
    "OVER_QUERY_LIMIT": "The webpage has gone over the requests limit in too short a period of time",
    "REQUEST_DENIED": "The webpage is not allowed to use the geoCoder for some reason",
    "INVALID_REQUEST": "This request was invalid",
    "ZERO_RESULTS": "The request did not encounter any errors but returns zero results",
    "ERROR": "There was a problem contacting the Google servers"
};

// LocationType
var GeocoderLocationTypeDescription = {
    "ROOFTOP": "The returned result reflects a precise geocode.",
    "RANGE_INTERPOLATED": "The returned result reflects an approximation (usually on a road) interpolated between two precise points (such as intersections). Interpolated results are generally returned when rooftop geocodes are unavilable for a street address.",
    "GEOMETRIC_CENTER": "The returned result is the geometric center of a result such a line (e.g. street) or polygon (region).",
    "APPROXIMATE": "The returned result is approximate."
};
//================================================ Variables END

//================================================ Init BEGIN
function initGeoSearch() {

    var defaultParams = getDefaultValue("params");

    var mapOptions = {
            'zoom' : (defaultParams.zoom ? defaultParams.zoom : 1),
            'center' : (defaultParams.center ? defaultParams.center : new google.geoMap.LatLng(0.0,0.0)),
            'mapTypeId' : (defaultParams.mapTypeId ? defaultParams.mapTypeId : google.maps.mapTpyeId.ROADMAP),
            'scaleControl': (defaultParams.scaleControl ? defaultParams : true),
            'navigationControl': (defaultParams.navigationControl ? defaultParams : true),
            'navigationControlOptions' : (defaultParams.navigationControlOptions ? defaultParams.navigationControlOptions : { style: google.maps.NavigationControlStyle.ZOOM_PAN }) 
    }

/*
'zoomControl': (defaultParams.zoomControl ? defaultParams : true),
'zoomControlOptions': (defaultParams.zoomControlOptions ? defaultParams.zoomControlOptions : { style: google.maps.ZoomControlStyle.SMALL }),
*/

        geoMap = new google.maps.Map(document.getElementById("mapGeoSearch"), mapOptions);
        geoCoder = new google.maps.Geocoder();
		//google.maps.event.trigger(geoMap, 'resize');

        geoInfoWindow = new google.maps.InfoWindow( {
            'size' : new google.maps.Size(292,120)
        });

        geoShadow = new google.maps.MarkerImage(
            MAPFILES_URL + "shadow50.png",
            new google.maps.Size(37, 34),
            new google.maps.Point(0, 0),
            new google.maps.Point(10, 34)
          );

        geoClickIcon = new google.maps.MarkerImage(
            MAPFILES_URL + 'dd-start.png',
            new google.maps.Size(20, 34),
            new google.maps.Point(0, 0),
            new google.maps.Point(10, 34)
          );


        google.maps.event.addListener(geoMap,'click',onClickCallback);

        // Bounds changes are asynchronous in v3, so we have to wait for the idle
        // event to ensure that viewport biasing picks up the correct viewport
        google.maps.event.addListener(geoMap, 'idle', function () {

            if (document.getElementById("inputGeoSearch").value && !initialized) {
                
                submitQuery();
            }
            initialized = true;
        });

        j++;

        domain = document.getElementById("Domain").value;
        domain = domain.substr(2, 2);

        groupZip = document.getElementById("arrGroupZip").value;

		//geoMap.setZoom(geoMap.getZoom());
}   
//================================================ Init END


//================================================ onClickCallback END
function onClickCallback(event) {

    // Setzte den Wert vom aktuellen Punkt wo gecklickt worden ist in das Steuerelement wo die eingabe stattfinden sollte!
    //document.getElementById("inputGeoSearch").value = event.latLng.toUrlValue(6);
    document.getElementById("hiddenGeoSearch").value = event.latLng.toUrlValue(6);
    geocode({ 'latLng': event.latLng });
}
//================================================ onClickCallback END


//================================================ Default values BEGIN
// Get the default value for various things
function getDefaultValue(art) {

    var defaultParams = {};
	var deflong;
	var deflat;
	
	try {
		deflong = 16;
		deflat = 48;
		deflong = document.getElementById("defaultLong").value;
		deflat = document.getElementById("defaultLat").value;
	}
	catch (ex)
	{
	}
	
    switch (art) {
        case 'params':
            defaultParams.zoom = 11;
            defaultParams.center = new google.maps.LatLng(deflat, deflong);
            defaultParams.mapTypeId = google.maps.MapTypeId.ROADMAP;
            defaultParams.scaleControl = true;
            defaultParams.navigationControl = true;
            defaultParams.navigationControlOptions = { style: google.maps.NavigationControlStyle.ZOOM_PAN }; 

            return defaultParams;
    }

// defaultParams.zoomControlOptions = { style: google.maps.ZoomControlStyle.SMALL }; 

}
//================================================ Default values END

//================================================ Actual values END
function setActualValue() {

    // Set actual values if we needed

}
//================================================ Actual values END


//================================================ Submit Query BEGIN
function submitQuery() {

    var inputGeoSearch = document.getElementById("inputGeoSearch").value + ',' + domain;

    if (/\s*^\-?\d+(\.\d+)?\s*\,\s*\-?\d+(\.\d+)?\s*$/.test(inputGeoSearch)) {
        
        var latlng = parseLatLng(inputGeoSearch);

        if (latlng == null) {
            document.getElementById("inputGeoSearch").value = "";
        } else {

                geocode({ 'latLng': latlng });
        }
    } else {

            geocode({ 'address': inputGeoSearch });
    }
}
//================================================ Submit Query END


//================================================ Geocode BEGIN
function geocode(request) {
    
    resetMap();                                                 //-> goto resetMap()
    
    var hash = '';

    if (request.latLng) {
        geoClickMarker = new google.maps.Marker({
            'position': request.latLng,
            'geoMap': geoMap,
            'title': request.latLng.toString(),
            'clickable': false,
            'icon': geoClickIcon,
            'shadow': geoShadow
        });
    } 

    // else {}

    // bounds = (47.42198,14.45213) - (49.02062, 17.06847)
    //var imageBounds = new google.maps.LatLngBounds(     new google.maps.LatLng(40.716216,-74.213393),     new google.maps.LatLng(40.765641,-74.139235));
    // var grenzgebiet = new google.maps.LatLngBounds(new google.maps.LatLng(47.42198, 14.45213), new google.maps.LatLng(49.02062, 17.06847));
    // request.bounds = grenzgebiet;
    request.region = domain;
    geoCoder.geocode(request,showResults);                     //-> goto showResults

}
//================================================ Geocode END


//================================================ ParseLatLng BEGIN
function parseLatLng(value) {

    value.replace('/\s//g');

    var coords = value.split(',');
    var lat = parseFloat(coords[0]);
    var lng = parseFloat(coords[1]);

    if (isNaN(lat) || isNaN(lng)) {
        return null;
    } else {
        return new google.maps.LatLng(lat, lng);
    }
}
//================================================ ParseLatLng END


//================================================ ShowResluts BEGIN
function showResults(results, status) {

    var counter = 0;
    var datastring = "";
    var tempresults;
    var reverse = (geoClickMarker != null);

    if (!results) {

        alert("Geocoder did not return a valid response");

    } else {

    var temptext = GeocoderStatusDescription[status];

        document.getElementById("infoGeoStatus").innerHTML = status;
        document.getElementById("infoGeoStatusDesc").innerHTML = GeocoderStatusDescription[status];

        if (status == google.maps.GeocoderStatus.OK) {
            document.getElementById("infoGeoFound").innerHTML = results.length;

            var textus = "";

            tempresults = new Array(results.length);

            for (var m = 0; m < results.length; m++) {

                datastring = getValidEntry(results[m]);

                if (datastring != "") {

                    tempresults[counter] = results[m];
                    counter += 1;
                }
            }

            results = new Array(counter);

            for (var n = 0; n < counter; n++) {

                results[n] = tempresults[n];
            }

            // Plot on Map!
            plotMatchesOnMap(results, reverse);                 //-> goto plotMatchesOnMap

          // ...sonst setze die Karte auf den Startpunkt zurück!
        } else {
            if (!reverse) {
                geoMap.setCenter(new google.maps.LatLng(0.0, 0.0));     //-> vielleich eher die Koordinaten des jeweiligen Staates!
                geoMap.setZoom(1);

                resetMap();
                document.getElementById("infoGeoSearch").innerHTML = "waiting for input...";
            }
        }
    }

    // Show any what u want after map is created!

}
//================================================ ShowResluts END


//======================================================================= 
//======================================================== GetAddressHTML
// Hier eruiere ich die würdigen Einträge für die Map ^^
function getValidEntry(result) {

    var components = result.address_components;

    var longname = "";
    var shortname = "";
    var typename = "";

    var datastring = "";

    for (var i = 0; i < components.length; i++) {

        longname = components[i].long_name;
        shortname = components[i].short_name;
        typename = components[i].types[0];


        switch (typename) {
            case "postal_code":
                datastring = longname;
                break;
            default:
                break;
        }
    }

    datastring = datastring.substr(0, 2);

    if (datastring == '') {
        datastring = '00';
    }
    else {
        if (groupZip.indexOf(datastring) < 0) {

            datastring = "";
        }
    }
    return datastring;
}

//======================================================================= 


//======================================================================= 
//================================================ PlotMatchesOnMap BEGIN
function plotMatchesOnMap(results, reverse) {

    geoMarkers = new Array(results.length);
    var resultsListHtml = "";

    var openInfoWindow = function (resultNum, result, marker) {

        return function () {
            if (selected != null) {

                document.getElementById('p' + selected).style.backgroundColor = "white";    //-> ???
                clearBoundsOverlays();                                                      //-> goto clearBoundsOverlays
            }

            geoMap.fitBounds(result.geometry.viewport);

            //§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
            // Ma reinschummeln um die Daten abzufangen und in unsere Datenfelder reinzukopieren!
            setAddressData(result);

            geoInfoWindow.setContent(getAddressHtml(result));
            geoInfoWindow.open(geoMap, marker);

            // -------------------------------------------------------------------------------------- INFO
            // Setzt die Grenzen von... #ff0000
            if (result.geometry.bounds) {
                boundsOverlay = new google.maps.Rectangle({
                    'bounds': result.geometry.bounds,
                    'strokeColor': '#fdbc11',
                    'strokeOpacity': 1.0,
                    'strokeWeight': 2.0,
                    'fillOpacity': 0.0
                });

                boundsOverlay.setMap(geoMap);
                google.maps.event.addListener(boundsOverlay, 'click', onClickCallback);

            } else {
                boundsOverlay = null;
            }

            // Könnt ma no anpassen, Styles, etc.!
            document.getElementById('p' + resultNum).style.backgroundColor = "#fdbc11";

            selected = resultNum;
        }
    }

        

    for (var i = 0; i < results.length; i++) {

        var icon = new google.maps.MarkerImage(
        
        getMarkerImageUrl(i),
        new google.maps.Size(20, 34),
        new google.maps.Point(0, 0),
        new google.maps.Point(10, 34)
    );

        // Create markers
        geoMarkers[i] = new google.maps.Marker({
            'position': results[i].geometry.location,
            'map': geoMap,
            'icon': icon,
            'shadow': geoShadow
        });

        setNetHotelsLatLng(results[i]);

        //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        // set 
        google.maps.event.addListener(geoMarkers[i], 'click', openInfoWindow(i, results[i], geoMarkers[i]));
        resultsListHtml += getResultsListItem(i, getResultDescription(results[i]));
    }
    
    
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    document.getElementById("infoGeoSearch").innerHTML = resultsListHtml;                     //-> ???

    // SCROLL OR NOT :)
    if (reverse) {

        // make a smooth movement to the clicked position
        geoMap.panTo(geoClickMarker.getPosition());
        google.maps.event.addListenerOnce(geoMap, 'idle', function () {
            selectMarker(0);                                           
        });
    }
    else {

        zoomToViewports(results);
//        geoMap.setCenter(new google.maps.LatLng(0.0, 0.0));
        geoMap.setZoom(2);
        selectMarker(0);                                         
    }
}
//================================================ PlotMatchesOnMap END


//======================================================================= 
//========================================================== SelectMarker 
function selectMarker(n) {

    google.maps.event.trigger(geoMarkers[n], 'click');
}
//=======================================================================


//======================================================================= 
//===================================================== GetMarkerImageUrl
function getMarkerImageUrl(resultNum) {

    return MAPFILES_URL + "marker" + String.fromCharCode(65 + resultNum) + ".png";
}
//======================================================================= 
//======================================================================= 


//======================================================================= 
//======================================================== SetAddressData
function setAddressData(result) {

    ResetSummary();

    var components = result.address_components;

    var longname = "";
    var shortname = "";
    var typename = "";
    var typesname = "";
    var resulttypes = ""
    var datastring = "";
    var datafull = "";
    var typenameold = "";

    document.getElementById("inputGeoSearch").value = result.formatted_address;
    document.getElementById("dataAddress").innerHTML = result.formatted_address;

    datafull = result.formatted_address + "(AddressString)";

    resulttypes = result.types.join("<br />");
    document.getElementById("dataTypes").innerHTML = resulttypes;

    for (var i = 0; i < components.length; i++) {
        
        longname = components[i].long_name;
        shortname = components[i].short_name;
        typename = components[i].types[0];

        datastring = typename + " | " + longname + " | " + shortname + "<br />";

        switch (typename) {
            case "street_address":
                document.getElementById("dataAddress").innerHTML = datafull;
                break;
            case "route":
                document.getElementById("dataRoute").innerHTML = datastring;             
                break;
            case "political":
                document.getElementById("dataPolitical").innerHTML = datastring;          
                break;
            case "country":
                document.getElementById("dataCountry").innerHTML = datastring;
                break;
            case "administrative_area_level_1":
                document.getElementById("dataFederalState").innerHTML = datastring;
                break;
            case "administrative_area_level_2":
                document.getElementById("dataCounty").innerHTML = datastring;
                break;
            case "administrative_area_level_3":
                document.getElementById("dataMunicipality").innerHTML = datastring;
                break;
            case "colloquial_area":
                document.getElementById("dataColloquial").innerHTML = datastring;        
                break;
            case "locality":
                document.getElementById("dataLocality").innerHTML = datastring;
                break;
            case "sublocality":
                document.getElementById("dataSubLocality").innerHTML = datastring;
                break;
            case "neighborhood":
                document.getElementById("dataNeighborhood").innerHTML = datastring;
                break;
            case "premise":
                document.getElementById("dataPremise").innerHTML = datastring;
                break;
            case "subpremise":
                document.getElementById("dataSubPremise").innerHTML = datastring;
                break;
            case "postal_code":
                document.getElementById("dataPostalCode").innerHTML = datastring;
                break;
            case "natural_feature":
                document.getElementById("dataNaturalFeature").innerHTML = datastring;
                break;
            case "airport":
                document.getElementById("dataAirport").innerHTML = datastring;
                break;
            case "park":
                document.getElementById("dataPark").innerHTML = datastring;
                break;
            case "post_box":
                document.getElementById("dataPostBox").innerHTML = datastring;
                break;
            case "street_number":
                document.getElementById("dataStreetNumber").innerHTML = datastring;
                break;
            default:
                break;
        }

        // Jetzt die Types noch, wer weiß für was es gut ist ;)
        for( var j = 1; j < components[i].types.length; j++) {

            typesname = components[i].types[j];

            if ((typesname != typenameold) & (resulttypes.indexOf(typesname) == 0)) {
             
                document.getElementById("dataTypes").innerHTML += "<br />" + typesname;
            }

            typenameold = typesname;
        }
    }
}
//======================================================================= 


//======================================================================= 
//======================================================== GetAddressHTML
// Das macht die Einträge für das Infowindow!
function getAddressHtml(result) {

    var html = '<div class="infoWindowContent">' +
               '<table class="tabContent">';

    html += tr("Address:<br />",result.formatted_address);
        html += br();

    html += '</table></div>';
    return html;
}

//======================================================================= 


//======================================================================= 
//==================================================== GetResultsListItem
// DES TEIL...macht die Einträge für die Liste!

function getResultsListItem(resultNum, resultDescription) {
    var html = '<a onclick="selectMarker(' + resultNum + ')">';

    html += '<div class="info" id="p' + resultNum + '">';
    html += '<table><tr valign="top">';
    html += '<td style="padding: 2px"><img src="' + getMarkerImageUrl(resultNum) + '"/></td>';
    html += '<td style="padding: 2px">' + resultDescription + '</td>';
    html += '</tr></table>';
    html += '</div></a>';

    return html;
}
//======================================================================= 


//======================================================================= 
//================================================== GetResultDescription
function getResultDescription(result) {

    var bounds = result.geometry.bounds;
    var html = '<table class="tabContent">';

    html += tr('', result.formatted_address);
    html += '</table>';

    // Schreib noch die Werte ind die Kontrolltabelle!
    document.getElementById("dataLocation").innerHTML = result.geometry.location.toString();
    document.getElementById("dataBounds").innerHTML = (bounds ? boundsToHtml(bounds) : "None");
    document.getElementById("dataViewport").innerHTML =  (boundsToHtml(result.geometry.viewport));

    return html;
}
//======================================================================= 

//======================================================================= 

function resetMap() {

    if (geoInfoWindow) {
        geoInfoWindow.close();
    }

    if (geoClickMarker != null) {
        geoClickMarker.setMap(null);
        geoClickMarker = null;
    }

    for (var i in geoMarkers) {

        var item;
        var numberOfResults = geoMarkers.length;

        for (var i = 0; i < numberOfResults; i++) {
            item = geoMarkers[i];

            if (item != null) {

                geoMarkers[i].setMap(null);
            }
        }
    }


    geoMarkers = [];
    selected = null;
    clearBoundsOverlays();
}

// Update map if container resize
function updateMap(map) {
	
	if(map) {

		initGeoSearch();
	}
	else {

		alert("Error! No map!");
	}
}


//======================================================================= 

function clearBoundsOverlays() {

    if (boundsOverlay != null) {

        boundsOverlay.setMap(null);
    }
 }

//======================================================================= 
// Hier bekommen wir die richtige Daten für Nethotels LatLng abfragen zurück!
 function setNetHotelsLatLng(result) {

     if (result != null) {

         var SWstring = result.geometry.location.toString();
         SWstring = SWstring.substring(1, SWstring.length - 1);
         var SWdata = SWstring.split(",");

         // Set the hidden field on (provider)address
         //alert("SWLat: " + SWdata[0] + " | SWLng: " + SWdata[1]);
         document.getElementById("addressLngLat").value = "[" + SWdata[1] + "," + SWdata[0] + "]";

     }
 }


//======================================================================= 

 function boundsToHtml(bounds) {

    return '(' +
    bounds.getSouthWest().toUrlValue(6) +
    ') -<br/>(' +
    bounds.getNorthEast().toUrlValue(6) +
    ')';
}

//======================================================================= 

function tr(lable,value) {

    return "<tr><td>" + lable + value + "</td></tr>";
}

//======================================================================= 

// DES TEIL... macht den Border untder den eizelnen teilen!!
function br() {

    return '<tr><td colspan="2"><div style="width: 100%; border-bottom: 1px solid grey; margin: 2px;"</td></tr>';
}


//======================================================================= 

function zoomToViewports(results) {

    var item;
    var bounds = new google.maps.LatLngBounds();
    var numberOfResults = results.length;
    
    for (var i = 0; i < numberOfResults; i++ ) {
        item = results[i];

        if (item.geometry != null) {
        
            bounds.union(item.geometry.viewport);
        }
    }

    geoMap.fitBounds(bounds);
}


//======================================================================= 

function setOptions(params) {

    if (params.query) {
        document.getElementById("inputGeoSearch").value = params.query // + ',' + domain;
        document.getElementById("hiddenGeoSearch").value = params.query // + ',' + domain;
    }
}


//======================================================================= 

function parseUrlParams() {

    var params = {};
    var inputGeoSearch = document.getElementById("hiddenGeoSearch").value;

    if (inputGeoSearch != "") {
        params.query = inputGeoSearch;
    }
    else {
        params.query = "0.0, 0.0";
    }

    return params;
}

//======================================================================= 

function ResetSummary() {

    var datafull = "";
    var datastring = "";

    document.getElementById("dataAddress").innerHTML = datafull;
    document.getElementById("dataRoute").innerHTML = datastring;             
    document.getElementById("dataPolitical").innerHTML = datastring;          
    document.getElementById("dataCountry").innerHTML = datastring;
    document.getElementById("dataFederalState").innerHTML = datastring;
    document.getElementById("dataCounty").innerHTML = datastring;
    document.getElementById("dataMunicipality").innerHTML = datastring;
    document.getElementById("dataColloquial").innerHTML = datastring;        
    document.getElementById("dataLocality").innerHTML = datastring;
    document.getElementById("dataSubLocality").innerHTML = datastring;
    document.getElementById("dataNeighborhood").innerHTML = datastring;
    document.getElementById("dataPremise").innerHTML = datastring;
    document.getElementById("dataSubPremise").innerHTML = datastring;
    document.getElementById("dataPostalCode").innerHTML = datastring;
    document.getElementById("dataNaturalFeature").innerHTML = datastring;
    document.getElementById("dataAirport").innerHTML = datastring;
    document.getElementById("dataPark").innerHTML = datastring;
    document.getElementById("dataPostBox").innerHTML = datastring;
    document.getElementById("dataStreetNumber").innerHTML = datastring;
    document.getElementById("dataTypes").innerHTML = datastring;
}

