// GoogleMap class 
GoogleMap = function(){
    var MARKER_MIN_ZOOM = 12;
    var MARKER_CLUSTER_ZOOM = 8;
    var map_instance = null;
    var marker_backend = null;
    var markers = null;
    var marker_mgr = null;
    var bounds = null;
    var icons = null;
    var needrefresh = true;
    var clusterer = null;
    var first_load = true;
    
    this.init = function(element_id, m_backend){
        map_instance = new GMap2(document.getElementById(element_id));
        this.map_instance = map_instance;
        this.geocoder = new GClientGeocoder();
        marker_backend = m_backend;
        this.marker_backend = marker_backend;
        markers = {};//new Array();
        this.markers = markers;
        if (typeof(MarkerManager) == 'undefined')
            marker_mgr = new GMarkerManager(this.map_instance);
        else
            marker_mgr = new MarkerManager(this.map_instance);
        this.marker_mgr = marker_mgr;
        // to remove
        var needrefresh;
        icons = new Array();
        this.icons = icons;
        bounds = new GLatLngBounds();
        this.bounds = bounds;
        
        // without initial positioning an error occured
        //this.map_instance.setCenter(new GLatLng(61.52401, 105.318756), 2);
        //clusterer = new MarkerClusterer(map_instance);
        //this.clusterer = clusterer;
        
        // system icons
        this.icons['mapobject'] = new GIcon();
        this.icons['mapobject'].shadow = "/media/img/gmapicons/mapobject_shadow.png";
        this.icons['mapobject'].image = "/media/img/gmapicons/mapobject.png";
        this.icons['mapobject'].iconSize = new GSize(25, 34);
        this.icons['mapobject'].iconAnchor = new GPoint(12, 34);
        this.icons['mapobject'].infoWindowAnchor = new GPoint(64, 35);
        
        this.icons['event'] = new GIcon(this.icons['mapobject']);
        this.icons['event'].image = "/media/img/gmapicons/event.png";
        this.icons['event'].shadow = "/media/img/gmapicons/event_shadow.png";
        
        this.icons['goods'] = new GIcon(this.icons['mapobject']);
        this.icons['goods'].image = "/media/img/gmapicons/goods.png";
        this.icons['goods'].shadow = "/media/img/gmapicons/goods_shadow.png";
        
        this.icons['cluster_mapobject'] = new GIcon(this.icons['mapobject']);
        this.icons['cluster_event'] = new GIcon(this.icons['event']);
        this.icons['cluster_goods'] = new GIcon(this.icons['goods']);
        //this.icons['mini'].image = "/media/img/gmapicons/mini_marker.png";
        //this.icons['mini'].iconSize = new GSize(10, 10);
        //this.icons['mini'].iconAnchor = new GPoint(5, 5);
        
        var customUI = this.map_instance.getDefaultUI();
        customUI.maptypes.hybrid = false;
        customUI.maptypes.satellite = false;
        customUI.maptypes.physical = false;
        this.map_instance.setUI(customUI);
        this.map_instance.disableScrollWheelZoom();
        
        
        //GEvent.addListener(map_instance, 'infowindowclose', function(){alert('!!!')});
        //GEvent.addListener(this.map_instance, "infowindowopen", function () {
            //this.savePosition();
        //});
        //GEvent.addListener(this.map_instance, "infowindowclose", function () {
            //this.returnToSavedPosition();
        //});
       //gmap.setUIToDefault();
        //gmap.enableDoubleClickZoom();
        //gmap.addControl(new GMapTypeControl());
        //gmap.addControl(new GLargeMapControl());
    }

    createMarker = function(stores) {
        var store = stores[0];
        var newIcon = store.icon;
        var marker = new GMarker(store.latlng, {icon: newIcon});
        marker.object_id = store.id;
        marker.backend = store.backend;
        GEvent.addListener(marker, 'click', function() {
            this.openExtInfoWindow(
                map_instance,
                "custom_info_window_bubble",
                '<div align="center"><img src="/media/img/ajax-loader.gif" /></div>',
                {
                    ajaxUrl: this.backend + this.object_id + '/',
                    beakOffset: 1
                }
            );
        });
        return marker;
    }

    createClusteredMarker = function(stores) {
        var newIcon = stores[0].icon;
        var marker = new GMarker(stores[0].latlng, {icon: newIcon});
        var query = "?";
        for (var i = 0; i < stores.length; i++) {
            query += 'ids=' + stores[i].id + '&';
        } 
        marker.backend = stores[0].backend;
        GEvent.addListener(marker, 'click', function() {
            this.openExtInfoWindow(
                map_instance,
                "custom_info_window_bubble",
                '<div align="center"><img src="/media/img/ajax-loader.gif" /></div>',
                {
                    ajaxUrl: this.backend + 'cluster/' + query,
                    beakOffset: 1
                }
            );
        });
        return marker;
    }

    markers_update = function(){
        b = map_instance.getBounds();
        d = new Date();
        $.post(marker_backend, 
            {'bounds': "" + b}, 
            function(json) {
                eval("var data = " + json + ";");
                if (typeof(data['error']) != 'undefined')
                    alert(data['error']);
                else {
                    load_points(data);
                }
            }
        );
    }
    
    this.set_focus = function(searchtext, ratio, latitude, longitude){
        ratio = typeof(ratio) != 'undefined' ? ratio : 10;
        latitude = typeof(latitude) != 'undefined' ? latitude : null;
        longitude = typeof(longitude) != 'undefined' ? longitude : null;
        MARKER_MIN_ZOOM = ratio;
        if (latitude && longitude){
            this.map_instance.setCenter(new GLatLng(latitude, longitude), ratio);
        }
        else if (searchtext){
            this.geocoder.getLatLng(
                searchtext,
                function(point) {
                    if (!point) {
                        alert("\"" + searchtext + "\" not found");
                    } else {
                        map_instance.setCenter(point, ratio);
                    }
                }
            );
        }
        GEvent.addListener(this.map_instance, "moveend", function () {
            markers_update();
        });
        //big_map_update(this.map_instance, this.marker_mgr);
    }
    
    //#############
    // new
    //#############
    AdditionalControls = function(){};
    AdditionalControls.prototype = new GControl();

    AdditionalControls.prototype.initialize = function(map) {
        var container = document.createElement("div");
        var back_div = document.createElement("div");
        this.setButtonStyle_(back_div);
        container.appendChild(back_div);
        img = document.createElement("img");
        img.src = '/media/img/btn-map-back.gif'
        back_div.appendChild(img);
        GEvent.addDomListener(back_div, "click", function() {
            map.returnToSavedPosition();
            map.removeControl(add_control_back);
        });
        
        map.getContainer().appendChild(container);
        return container;
    }

    AdditionalControls.prototype.getDefaultPosition = function() {
        return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7));
    }

    AdditionalControls.prototype.setButtonStyle_ = function(button) {
        button.style.textDecoration = "underline";
        button.style.cursor = "pointer";
    }

    var add_control_back = new AdditionalControls();

    // markers
    
    load_points = function(pts, markerstype){
        var locations = {};
        var cluster_locations = {};
        if (typeof(markerstype) == 'undefined')
            var cluster_icon = icons['cluster_mapobject'];
        else {
            if (markerstype == 'mapobjects')
                var cluster_icon = icons['cluster_mapobject'];
            if (markerstype == 'events')
                var cluster_icon = icons['cluster_event'];
            if (markerstype == 'goods')
                var cluster_icon = icons['cluster_goods'];
        }
        
        if (first_load){
            var total_bounds = new GLatLngBounds();
            for (i=0; i<pts.length; i++){
                total_bounds.extend(new GLatLng(pts[i]['latitude'], pts[i]['longitude']));
            }
            map_instance.setCenter(total_bounds.getCenter());
            map_instance.setZoom(map_instance.getBoundsZoomLevel(total_bounds));
            first_load = false;
        }
        for (var i = 0; i < pts.length; i++) {
            var latlng = new GLatLng(pts[i]['latitude'], pts[i]['longitude']);
            var store = {latlng: latlng, 
                         icon:  icons[pts[i]['type']],
                         id: pts[i]['id'],
                         backend: pts[i]['backend']};
            var latlngHash = (latlng.lat().toFixed(6) + "" + latlng.lng().toFixed(6) + "" + pts[i]['type']);
            latlngHash = latlngHash.replace(".","").replace(".", "").replace("-","");
            if (locations[latlngHash] == null) {
                locations[latlngHash] = []
            }
            locations[latlngHash].push(store);
            if (cluster_locations[pts[i]['city__id']] == null) {
                cluster_locations[pts[i]['city__id']] = []
            }
            cluster_locations[pts[i]['city__id']].push(latlng);
        }
        //cluster
        var cluster_mrk = [];
        for (var latlng_item in cluster_locations) {
            var bnds = new GLatLngBounds();
            for (i = 0; i < cluster_locations[latlng_item].length; i++)
                bnds.extend(cluster_locations[latlng_item][i]);
            var center = bnds.getCenter();
            var cluster_marker = new GMarker(center, {icon: cluster_icon});
            GEvent.addListener(cluster_marker, "click", function() {
                map_instance.savePosition();
                map_instance.setCenter(this.getLatLng(), MARKER_CLUSTER_ZOOM+1);
                //map_instance.addControl(add_control_back);
            });
            if (typeof(markers[latlng_item]) == 'undefined'){
                cluster_mrk.push(cluster_marker);
                markers[latlng_item] = cluster_marker;
            }
        }
        marker_mgr.addMarkers(cluster_mrk, 0, MARKER_CLUSTER_ZOOM);
        //full
        var mrk = [];
        for (var latlngHash in locations) {
            var stores = locations[latlngHash];
            if (typeof(markers[latlngHash]) == 'undefined'){
                if (stores.length > 1) {
                    markers[latlngHash] = createClusteredMarker(stores);
                } else {
                    markers[latlngHash] = createMarker(stores);
                }
                mrk.push(markers[latlngHash]);
            }
        }
        marker_mgr.addMarkers(mrk, MARKER_CLUSTER_ZOOM+1, 17);
        marker_mgr.refresh();
        //if (update){
            
            //map_instance.setCenter(bnds.getCenter());
            //map_instance.setZoom(map_instance.getBoundsZoomLevel(bnds));
            //map_instance.savePosition();
        //}else {
            //marker_mgr.addMarkers(mrk, 2);
            
        //}
        //marker_mgr.refresh();
        }
    
    this.load_points = load_points;
}
