﻿LocationFinder = new function() {
    this.startLat = -30.00;
    this.startLng = 145.00;
    this.startZoom = 3;
    this.defaultCountry = 'australia';
    this.forceDefaultCountry = true;
    this.map;

    var useDialog = true;
    var mapBufferPx = 25;
    var self = this;
    var currentCenter;
    var geocoder;
    var locations = new Array();
    var locationTypes = new Object();

    this.initialize = function() {
        map = new google.maps.Map2(document.getElementById("map_canvas"));
        geocoder = new GClientGeocoder();
        currentCenter = new GLatLng(self.startLat, self.startLng)
        map.setCenter(currentCenter, self.startZoom);
        map.setUIToDefault();
        map.disableScrollWheelZoom();
    };

    function calculateNewCenter(data) {
        var bounds;
        for (i = 0; i < data['locations'].length; i++) {
            var loc = data['locations'][i];
            var latLgt = new GLatLng(loc['latitude'], loc['longitude']);
            if (latLgt) {
                if (!bounds) {
                    bounds = new GLatLngBounds(latLgt);
                }
                else {
                    bounds.extend(latLgt);
                }
            }
        }
        return bounds.getCenter();
    }

    function getRestrictedLocationsSet(data) {
        var restrictedData = new Object();
        restrictedData['distance_degrees'] = data['distance_degrees'];
        restrictedData['locations'] = new Array();
        restrictedData['count'] = 0;
        var addedLocations = 0;

        var centerPoint = calculateNewCenter(data); //GLatLng

        for (i = 0; i < data['locations'].length; i++) {
            var loc = data['locations'][i];
            var latLgt = new GLatLng(loc['latitude'], loc['longitude']);
            if (latLgt) {
                var distance = centerPoint.distanceFrom(latLgt) / 1000;
                if (distance > 200.00 && addedLocations < 3) {
                    break;
                }
                if (addedLocations == 8) {
                    break;
                }
                restrictedData['locations'][i] = data['locations'][i];
                restrictedData['count'] = i + 1;
                addedLocations++;
            }
        }

        return restrictedData;
    }

    this.setLocations = function(data) {
        locations = data['locations'];
        updateMap(data);
    }

    this.setLocationTypes = function(data) {
        locationTypes = data;
    }

    this.showMessage = function(message) {
        var errorMessageSpan = $("span.errorMessage");
        errorMessageSpan.text(message);
        return true;
    };

    this.gcodeCallback = function(data) {
        if (!data) {
            self.showMessage('Sorry, the address/postcode entered could not be found.');
            return;
        }
        document.location.href = document.location.pathname + '?lat=' + data.lat() + '&lng=' + data.lng() + '#Map';
        return;
    }

    this.getCoordinates = function() {
        var q_postcode = null;
        var query = $("input.coordinates").val();
    
        q_postcode = getQuerystring('q');
        self.showMessage('');

        if (q_postcode !== '') {
            query = q_postcode;
        }

        if (query !== null) {

            var address = query ? query.replace(/(^\s*)|(\s*$)/g, '') : '';
            if (!address) return false;
            if (self.forceDefaultCountry && (address.toLowerCase() != self.defaultCountry.toLowerCase())) {
                address += ' ' + self.defaultCountry;
            }
            gcoder = new GClientGeocoder();
            gcoder.getLatLng(address, LocationFinder.gcodeCallback);
            return true;
        }
        return false;
    };

    function getQuerystring(key, default_) {
        if (default_ == null) default_ = "";
        key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
        var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
        var qs = regex.exec(window.location.href);
        if (qs == null)
            return default_;
        else
            return qs[1];
    }

    function updateMap(data) {
        var i, loc, point, marker, icon, baseIcon;
        var minLat, maxLat, minLng, maxLng;
        var minLatLng, maxLatLng, bounds, zoom;
        var minLatLngPx, maxLatLngPx;

        if (!map) {
            map = new google.maps.Map2(document.getElementById("map_canvas"));
        }
        map.clearOverlays();

        currentCenter = calculateNewCenter(data);

        // Show search origin
        if (self.showSearchLocation) {
            icon = new GIcon();
            icon.image = 'http://maps.google.com/mapfiles/kml/pal4/icon47.png';
            icon.size = new GSize(16, 16);
            icon.iconAnchor = new GPoint(8, 8);
            map.addOverlay(new GMarker(currentCenter, { 'icon': icon, 'clickable': false, 'title': 'Your location' }));
        }
        minLat = maxLat = currentCenter.lat();
        minLng = maxLng = currentCenter.lng();

        // Show locations found
        baseIcon = new GIcon();
        baseIcon.image = 'http://www.google.com/intl/en_ALL/mapfiles/marker.png';
        baseIcon.iconSize = new GSize(20, 34);
        baseIcon.iconAnchor = new GPoint(10, 34);
        baseIcon.shadow = 'http://www.google.com/intl/en_ALL/mapfiles/shadow50.png';

        for (i = 0; i < data['locations'].length; i++) {
            loc = data['locations'][i];
            loc['detailsElement'] = getDetailsElementByIndex(i);
            point = new GLatLng(loc['latitude'], loc['longitude']);
            var locType = locationTypes[loc['locationTypeID']];
            if (locType && locType['iconURL']) {
                icon = new GIcon();
                icon.image = locType['iconURL'];
                icon.iconSize = new GSize(locType['iconWidth'], locType['iconHeight']);
                icon.iconAnchor = new GPoint(locType['iconAnchorX'], locType['iconAnchorY']);
                if (locType['iconShadowURL']) {
                    icon.shadow = locType['iconShadowURL'];
                }
            }
            else {
                icon = new GIcon(baseIcon);
                icon.image = 'http://www.google.com/intl/en_ALL/mapfiles/marker' + String('ABCDEFGHIJKLMNOPQRSTUVWXYZ').charAt(i) + '.png';
            }
            marker = new GMarker(point, { 'icon': icon, 'clickable': true, 'title': loc['name'] });
            loc['marker'] = marker;
            if (locType && locType['iconURL'] && locType['iconHighlightURL']) {
                GEvent.addListener(marker, "mouseover", getEventHandler('mouseover', i));
                GEvent.addListener(marker, "mouseout", getEventHandler('mouseout', i));
                GEvent.addListener(marker, "click", getEventHandler('click', i));
            }

            map.addOverlay(marker);
            minLat = Math.min(minLat, point.lat());
            maxLat = Math.max(maxLat, point.lat());
            minLng = Math.min(minLng, point.lng());
            maxLng = Math.max(maxLng, point.lng());
        }

        if (data['locations'].length == 0) {
            minLatLng = new GLatLng(currentCenter.lat() - data['distance_degrees'], currentCenter.lng() - data['distance_degrees']);
            maxLatLng = new GLatLng(currentCenter.lat() + data['distance_degrees'], currentCenter.lng() + data['distance_degrees']);
            bounds = new GLatLngBounds(minLatLng, maxLatLng)
            zoom = map.getBoundsZoomLevel(bounds);
            map.setCenter(currentCenter, zoom);
            map.disableScrollWheelZoom();
            self.showMessage('Sorry, no locations were found matching your search. Please check your spelling, or try searching a neighbouring town or suburb.');
        }
        else {
            minLatLng = new GLatLng(minLat, minLng);
            maxLatLng = new GLatLng(maxLat, maxLng);
            bounds = new GLatLngBounds(minLatLng, maxLatLng)
            zoom = map.getBoundsZoomLevel(bounds);
            map.setCenter(bounds.getCenter(), zoom);
            map.disableScrollWheelZoom();
            minLatLngPx = map.fromLatLngToDivPixel(minLatLng);
            maxLatLngPx = map.fromLatLngToDivPixel(maxLatLng);
            if (maxLatLngPx.y < mapBufferPx) {
                map.setZoom(--zoom);
            }
        }
    } //end updateMap

    function getDetailsElementByIndex(idx) {
        var container = document.getElementById('locationList');
        if (!container) return null;
        var items = container.getElementsByTagName('li');
        if (!items || items.length == 0) return null;
        var element = items.item(idx);
        return element;
    }

    function getEventHandler(type, idx) {
        var handler;
        switch (type) {
            case 'click':
                handler = function() { self.focusLocation(idx, true); };
                break;
            case 'mouseover':
                handler = function() { self.focusLocation(idx, false); };
                break;
            case 'mouseout':
                handler = function() { self.clearFocus(false); };
                break;
        }
        return handler;
    }


    this.focusLocation = function(idx, sticky) {
        for (i = 0; i < locations.length; i++) {
            var loc = locations[i];
            var locType = locationTypes[loc['locationTypeID']];
            if (i == idx && !(loc['current'] && sticky)) {
                if (sticky) {
                    loc['current'] = true;
                }
                if (!/\bcurrent\b/.test(loc['detailsElement'].className)) { loc['detailsElement'].className += ' current'; }
                if (locType && locType['iconHighlightURL']) { loc['marker'].setImage(locType['iconHighlightURL']); }
            }
            else {
                if (sticky) { loc['current'] = false; }
                if (!loc['current']) {
                    loc['detailsElement'].className = loc['detailsElement'].className.replace(/\bcurrent\b/, '').replace(/(^\s*)|(\s*$)/g, '');
                    if (locType && locType['iconURL']) { loc['marker'].setImage(locType['iconURL']); }
                }
            }
        }
    }

    this.clearFocus = function(clearSticky) {
        self.focusLocation(-1, clearSticky);
    }
}
