var amli_map = AMLI.Map = function() {

    return {
        init: function(data, opts, elementid) {

            this.Data = data;
            this.center = this.defaultCenter = opts.center ? opts.center : null;
            this.zoom = this.defaultZoom = opts.zoom ? opts.zoom : 4;
            this.Element = _get(elementid);
            this.ALPHABET = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
            this.dbupdates = location.search.indexOf('dbupdates') > -1;

            if (GBrowserIsCompatible()) {

                this.map = new GMap2(this.Element, { mapTypes: [G_PHYSICAL_MAP] });
                this.map.addControl(new GSmallZoomControl());

                window.setTimeout("AMLI.Map.drawMarkers();", 250);
            }
        },
        drawMarkers: function() {

            this.bounds = null;
            this.markermgr = new GMarkerManager(this.map, { trackMarkers: true });
            this.markers = new Array();

            for (var s in this.Data) {
                var item = this.Data[s];

                if (item.lat && item.lng) {

                    var p = new GLatLng(item.lat, item.lng);
                    var i = new GIcon(G_DEFAULT_ICON, '/images/markers/marker_red_' + item.mrk + '.png');

                    if (this.bounds == null) {
                        this.bounds = new GLatLngBounds(p, p);
                    } else {
                        this.bounds.extend(p);
                    }

                    var marker = this.markers[this.markers.length] = new GMarker(p, { title: item.name, icon: i });
                    this.map.addOverlay(marker);

                    marker.dataItem = item;
                    this.addListeners(marker);

                } else if (this.dbupdates) {

                    if (!this.geocoder) this.geocoder = new GClientGeocoder();

                    this.geocoder.getLocations(item.addr.replace('<br />', ', ').replace(/-\d*$/, ''), this.showGeoCodeResponse(item));
                }
            }

            if (!this.center) {

                if (this.defaultCenter) {

                    this.center = this.defaultCenter;
                } else if (this.bounds) {

                    this.center = this.defaultCenter = this.bounds.getCenter();
                    this.zoom = this.defaultZoom = this.map.getBoundsZoomLevel(this.bounds);
                } else {

                    this.center = this.defaultCenter = new GLatLng(0, 0);  // TODO: Find US center.
                }
            }

            this.map.setCenter(this.center, this.zoom);
        },
        highlightFavs: function() {

            for (var i = 0; i < this.markers.length; i++) {

                if (this.markers[i].dataItem && this.markers[i].dataItem.fav) {

                    var marker = this.markers[i];
                    marker.setImage(marker.getIcon().image.replace('red', 'green'));
                }
            }
        },
        addListeners: function(marker) {
            GEvent.addListener(marker, 'mouseover', this.getMapEventFunction('markermouseover', marker, 'com_reg_' + marker.dataItem.id));
            GEvent.addListener(marker, 'mouseout', this.getMapEventFunction('markermouseout', marker, 'com_reg_' + marker.dataItem.id));
            GEvent.addListener(marker, 'click', this.getMapEventFunction('markerclick', marker, 'com_reg_' + marker.dataItem.id));

            var comReg = _get('com_reg_' + marker.dataItem.id);
            if (comReg) {
                GEvent.addDomListener(
                    comReg,
                    'mouseover',
                    this.getMapEventFunction(
                        'dommouseover',
                        marker,
                        'com_reg_' + marker.dataItem.id
                    )
                );

                GEvent.addDomListener(
                    comReg,
                    'mouseout',
                    this.getMapEventFunction(
                        'dommouseout',
                        marker,
                        'com_reg_' + marker.dataItem.id
                    )
                );
            }

            var comRegMap = _get('com_reg_' + marker.dataItem.id + '_map');
            if (comRegMap) {
                GEvent.addDomListener(
                    comRegMap,
                    'click',
                    this.getMapEventFunction(
                        'domclick',
                        marker,
                        'com_reg_' + marker.dataItem.id + '_map'
                    )
                );
            }
        },
        getMapEventFunction: function(eventtype, marker, elid) {

            var refMarker = marker;
            var refEl = _get(elid);

            switch (eventtype) {

                case 'markermouseover':
                    return function() {
                        if (refEl) refEl.style.backgroundColor = '#CAD6B0';
                        refMarker.setImage(refMarker.getIcon().image.replace('red', 'green'));
                    };

                case 'markermouseout':
                    return function() {
                        if (refEl) refEl.style.backgroundColor = '';
                        refMarker.setImage(refMarker.getIcon().image.replace('green', 'red'));
                    };

                case 'markerclick':
                    return function() {
                        refMarker.openInfoWindowHtml(
                            '<b>' + refMarker.dataItem.name + '</b><br/>'
                            + refMarker.dataItem.addr
                        );
                    };

                case 'dommouseover':
                    return function() {
                        if (refEl) refEl.style.backgroundColor = '#CAD6B0';
                        refMarker.setImage(refMarker.getIcon().image.replace('red', 'green'));
                    };

                case 'dommouseout':
                    return function() {
                        if (refEl) refEl.style.backgroundColor = '';
                        refMarker.setImage(refMarker.getIcon().image.replace('green', 'red'));
                    };

                case 'domclick':
                    return function() {
                        refMarker.openInfoWindowHtml(
                            '<b>' + refMarker.dataItem.name + '</b><br/>'
                            + refMarker.dataItem.addr
                        );
                    };
            }

        },
        showGeoCodeResponse: function(item) {

            var refThis = this;
            var refItem = item;

            return function(response) {

                switch (response.Status.code) {

                    case 200: // good
                        var place = response.Placemark[0];
                        var point = new GLatLng(place.Point.coordinates[1],
                                                place.Point.coordinates[0]);

                        var letterIcon = new GIcon(G_DEFAULT_ICON, '/images/markers/marker_green_' + refItem.mrk + '.png');

                        var marker = new GMarker(point, { title: refItem.name, icon: letterIcon });
                        refThis.map.addOverlay(marker);

                        if (refThis.dbupdates) {

                            if (!refThis.dbupdateTA) {
                                refThis.dbupdateTA = document.createElement('textarea');
                                document.body.appendChild(refThis.dbupdateTA);
                                refThis.dbupdateTA.style.width = '800px';
                                refThis.dbupdateTA.style.height = '200px';
                                refThis.dbupdateTA.value = '';
                            }
                            refThis.dbupdateTA.value += 'update global.dbo.communities set property_longitude=' + point.lng() + ', property_lattitude=' + point.lat() + ' where property_tag=\'' + refItem.id + '\';\r\n';
                        }

                        break;

                    default:
                        if (refThis.dbupdates)
                            alert('Google Maps error code: ' + response.Status.code + ' for ' + refItem.addr.replace('<br />', '\n').replace(/-\d*$/, ''));

                }

            };
        },
        search: function(srchstr) {

            if (srchstr != 'Search map...' && srchstr != 'Neighborhood search...') {

                this.reset();

                this.searcher = new google.search.LocalSearch();
                this.searcher.setCenterPoint(this.map.getCenter());
                this.searcher.setNoHtmlGeneration();
                this.searcher.setSearchCompleteCallback(this, this.drawSearch);
                this.searcher.setResultSetSize(GSearch.LARGE_RESULTSET);
                this.searcher.execute(srchstr);
            }
        },
        drawSearch: function() {

            var res = this.searcher.results;

            for (var i = 0; i < res.length && i < 8; i++) {
                var point = new GLatLng(res[i].lat, res[i].lng);
                var marker = this.markers[this.markers.length] = new GMarker(point, { title: res[i].titleNoFormatting, icon: new GIcon(G_DEFAULT_ICON, '/images/markers/marker_green_' + this.ALPHABET[i] + '.png') });
                this.map.addOverlay(this.markers[this.markers.length - 1]);

                this.bounds.extend(point);
                this.map.setCenter(this.bounds.getCenter(), this.map.getBoundsZoomLevel(this.bounds));
            }
        },
        getDirections: function(fromAddress, toAddress) {
            this.map.clearOverlays();
            if (this.directions) this.directions.clear();
            this.directionsPanel = _get('GDirections');
            this.directionsPanel.style.height = '';
            this.directions = new GDirections(this.map, this.directionsPanel);
            this.fromAddress = fromAddress;
            this.toAddress = toAddress;
            this.directions.load('from: ' + this.fromAddress + ' to: ' + this.toAddress);
        },
        reset: function() {

            this.map.clearOverlays();
            this.center = this.defaultCenter;
            this.zoom = this.defaultZoom;
            this.map.setCenter(this.center, this.zoom);
            this.drawMarkers();
        },
        getNewOpts: function() {

            return new AMLI.Map.Opts(this.map.getCenter().lat(), this.map.getCenter().lng(), this.map.getZoom());
        },
        refresh: function(opts) {

            if (this.center != opts.center) {
                this.center = opts.center;
                this.map.panTo(this.center);
            }
            if (this.zoom != opts.zoom) {
                this.zoom = parseInt(opts.zoom);
                this.map.setZoom(this.zoom);
            }
        }
    };

} ();


AMLI.Map.Opts = function(lat, lng, zoom) {

    this.lat = lat;
    this.lng = lng;
    this.zoom = zoom;
    this.center = (this.lat && this.lng) ? new GLatLng(this.lat, this.lng) : null;
};