/**
 * Location form processing
 */
Geo = {
    // Object for map processing
    mapApi: null,
    // Main marker on the map
    pointMarker: null,
    // Init flag
    isInit: false,
    // Google geocoder service
    geocoder: null,
    // Google marker cluster builder
    cluster: null,

    initMap: function(map, options) {
        this.mapApi = GMapApi(map, options);
        this.isInit = true;
        return this.mapApi;
    },

    getPointMarker: function(count, title) {
        count = count || 1;

        if (!this.pointMarker) {
            center = this.mapApi.map.getCenter();
            while(count--) {
                this.pointMarker = this.mapApi.addMarker({
                    position: center,
                    title: title
                });
            }
        }

        return this.pointMarker;
    },

    movePointMarker: function(point) {
        this.getPointMarker().setPosition(point);
    },

    setPointMarkerOption: function(options) {
        this.getPointMarker().setOptions(options);
    },

    // Set new listeners for events with point marker
    setPointMarkerEvents: function(events) {
        $.each(events, function(){
            google.maps.event.addListener(Geo.getPointMarker(), this.name, this.callback);
        });
    },

    // Move marker with center of the map
    // point : {lat, lng, zoom}
    panMapTo: function(point) {
        gpoint = this.mapApi.getPoint(point.lat, point.lng);

        this.movePointMarker(gpoint);
        this.mapApi.map.panTo(this.getPointMarker().getPosition());

        if (0 !== point.zoom) {
            this.mapApi.map.setZoom(point.zoom);
        }
    },

    geocodeAddress: function(address, callback) {
        this.getGeocoder().geocode(
            {'address': address},
            function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    callback(results[0].geometry.location);
                } else {
                    alert(Lang._("Geocode was not successful for the following reason:") + status);
                }
            }
        );
    },

    // Get point in {lat: , lng: } format
    geocodePoint: function(point, callback) {
        this.getGeocoder().geocode(
            {latLng: Geo.mapApi.getPoint(point.lat, point.lng)},
            function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    callback(results[0]);
                } else {
                    alert(Lang._("Geocode was not successful for the following reason:") + status);
                }
            }
        );
    },

    getGeocoder: function() {
        // Set up geocoder object, if its necessary
        if (!this.geocoder) {
            this.geocoder = new google.maps.Geocoder();
        }
        return this.geocoder;
    },

    showIndicator: function() {
        if (!this.mapApi) {
            return null;
        }

        return this.mapApi.showIndicator();
    },

    hideIndicator: function() {
        return this.mapApi.hideIndicator();
    },

    buildClusterFromMarker: function(marker, count) {
        count     = count || 1;
        locations = [];

        while(count--) {
            locations.push(marker);
        }
        this.getCluster(locations);
    },

    getCluster: function(markers, zoom) {
        if('undefined' == typeof(markers) || 1 == markers.length) {
            markers = this.mapApi.getMarkers();
        }

        zoom = zoom || 19;
        
        if (markers.length > 0) {
            this.cluster = new MarkerClusterer(this.mapApi.map, markers, {maxZoom: zoom});
        }

        return this.cluster;
    },

    clearCluster: function() {
        this.cluster.clearMarkers();
    },
    
    pointToString: function(lat, lng) {
        return parseFloat(lat).toFixed(5) + ':' + parseFloat(lng).toFixed(5); 
    }
}

/**
 * Gmap processor
 */
function GMapApi(map,options) {

    var m = {
        map: null,

        defaults : {
            zoom: 6,
            center : {
                lat: 41.87194,
                lng: 12.56738,
                zoom: 6
            },
            markers:		[],
            controls:		[],
            scrollwheel:	true,
            maptype:            google.maps.MapTypeId.ROADMAP,
            html_prepend:	'<div class="gmap_marker">',
            html_append:	'</div>',
            icon:               {
                image:              "http://google-maps-icons.googlecode.com/files/home.png",
                shadow:             "http://www.google.com/mapfiles/shadow50.png",
                iconsize:           [35, 35],
                shadowsize:         [35, 35],
                iconanchor:         [0, 0],
                infowindowanchor:   [18, 35]
            },
            streetView:             false
        },

        options : {},

        markers : [],

        indicator: null,

        getPoint: function(lat, lng) {
            return new google.maps.LatLng(lat, lng);
        },

        init: function(map) {
            this.map = new google.maps.Map(map, {
                zoom: this.options.center.zoom,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                center: this.getPoint(this.options.center.lat, this.options.center.lng),
                streetViewControl: this.options.streetView
            });

            // Load overlay to street view symbol
            this.initStreetViewOverlay();

            // Load map indicator
            this.initIndicator();
        },

        initStreetViewOverlay: function() {
            if (false === this.options.streetView) {
                return;
            }

            var DivUI = document.createElement('div');
            DivUI.innerHTML = '<div title="' 
                                + Lang._('Drag me to the location')
                                + '" style="width:75px;height:40px;position:absolute;top:90px;left:-80px;"></div>';
            DivUI.id = "geo_tooltip_drag";
            DivUI.index=1;
            this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(DivUI);
        },

        showIndicator: function() {
            this.getIndicator().style.display = "block";
        },

        hideIndicator: function() {
            this.getIndicator().style.display = "none";
        },

        initIndicator: function() {
            var IndicatorUI = document.createElement('div');
            IndicatorUI.innerHTML = '<div style="position:absolute;width:100%;border:5px;top:10px;left:50px;'
                                  + 'text-align:center;vertical-align:bottom;" id="geo_progress_text">'
                                  + '<img src="/img/ajax/loader.gif" />'
                                  + '</div>';
            IndicatorUI.id = "geo_load_indicator_container";
            IndicatorUI.style.display = "none";
            IndicatorUI.index=1;

            this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(IndicatorUI);
        },

        getIndicator: function() {
            if (!this.indicator) {
                indicator = document.getElementById('geo_load_indicator_container');
                if (indicator) {
                    this.indicator = indicator;
                } else {
                    return {style: {}};
                }
            }

            return this.indicator;
        },

        // Set up map controls
        controls: function(controls) {
            if (controls.length == 0) {
                this.map.setUIToDefault();
            } else {
                $.each(controls, function(i,element){
                    eval('this.map.addControl(new ' + element + '());');
                });
            }
        },

        addMarker: function(options) {
            options = $.extend(true, this.options, options);

            image = new google.maps.MarkerImage(
                options.icon.image,
                new google.maps.Size(options.icon.iconsize[0],options.icon.iconsize[1]),
                new google.maps.Point(options.icon.iconanchor[0],options.icon.iconanchor[1]),
                new google.maps.Point(options.icon.infowindowanchor[0], options.icon.infowindowanchor[1])
            );

            shadow = new google.maps.MarkerImage(
                options.icon.shadow,
                new google.maps.Size(options.icon.shadowsize[0], options.icon.shadowsize[1])
                //new google.maps.Point(this.options.icon.iconanchor[0],this.options.icon.iconanchor[1]),
                //new google.maps.Point(this.options.icon.infowindowanchor[0], this.options.icon.infowindowanchor[1])
            );
                
            marker = new google.maps.Marker({
                map: this.map,
                position: options.position,
                icon: image,
                title: (options.title || null)
            });

            // Add to history and return marker
            this.markers.push(marker);
            return marker;
        },

        setOptions: function(options) {
            this.options = $.extend({}, this.options, options);
        },

        markersWalk: function(callback) {
            $.each(this.markers, callback);
        },

        getMarkers: function() {
            return this.markers;
        }
    }
    // Build main options before element iteration
    m.options = $.extend({}, m.defaults, options);
    m.init(map);
    return m;
}
