function GmapsMarkerManager(b, a) {
    this.options = a || {};
    this.marker_size = new google.maps.Size(16, 32);
    this.setMap(b);
    this.map = b;
    this.markers = new Array();
    this.markers_infowindows = new Array();
    this.view_port = new Object();
    this.view_port.cell = new Object();
    this.view_port.cells = new Array();
    this.view_port.markers = new Array();
    this.view_port.cell.width = this.options.cell ? (this.options.cell.width || false) : this.marker_size.width * 3;
    this.view_port.cell.height = this.options.cell ? (this.options.cell.height || false) : this.marker_size.height * 3;
    this.view_port.height = this.map.getDiv().offsetHeight;
    this.view_port.width = this.map.getDiv().offsetWidth;
    this.view_port.cols_count = Math.ceil(this.view_port.width / this.view_port.cell.width);
    this.view_port.rows_count = Math.ceil(this.view_port.height / this.view_port.cell.height);
    this.initial = true;
    this.on_zoom = false;
    this.threshold_zoom = this.options.threshold || 12;
    this.group_icon_src = this.options.icon ? (this.options.icon.src || false) : false;
    this.group_icon_shadow = this.options.icon ? (this.options.icon.shadow || false) : false;
    this.grid = new Object();
    this.grid.cells = new Array();
    this.grid.markers = new Array()
}
GmapsMarkerManager.prototype = new google.maps.OverlayView();
GmapsMarkerManager.prototype.addMarker = function(a, b) {
    b = b || false;
    this.markers.push(a);
    this.markers_infowindows.push(b)
};
GmapsMarkerManager.prototype.removeMarkerByNumber = function(a) {
    this.markers[a].setMap(null);
    this.markers.splice(a, 1);
    this.initial = true;
    this.draw()
};
GmapsMarkerManager.prototype.clear = function(a) {
    for (var b in this.markers) {
        if (typeof this.markers[b] == "object") {
            this.markers[b].setMap(null)
        }
    }
    if (a) {
        this.markers = new Array()
    }
};
GmapsMarkerManager.prototype.draw = function() {
    if (this.initial) {
        this.refresh()
    }
    var a = this;
    google.maps.event.addListener(this.map, "zoom_changed",
    function() {
        a.initial = true
    })
};
GmapsMarkerManager.prototype.refresh = function() {
    this.clear();
    this.clearGroupMarkers();
    this.buildMapGrid(this.initial);
    this.checkMarkers(this.markers, this.view_port.cells);
    this.groupMarkers();
    this.initial = false
};
GmapsMarkerManager.prototype.clearGroupMarkers = function(a) {
    for (var b = 0; b < this.view_port.markers.length; b++) {
        if (this.view_port.markers[b].alias) {
            this.view_port.markers[b].alias.setMap(null)
        }
    }
    if (a) {
        this.view_port.markers = new Array()
    }
    return true
};
GmapsMarkerManager.prototype.buildMapGrid = function(b) {
    b = b || false;
    this.view_port.cells = this.buildGrid(this.calculateGridOptParams(this.markers));
    for (var a = 0; a < this.view_port.cells.length; a++) {
        if (typeof this.view_port.markers[a] == "undefined" || b) {
            this.view_port.markers[a] = new Object()
        }
    }
};
GmapsMarkerManager.prototype.calculateGridOptParams = function(b) {
    this.sanity = this.options.sanity || 1.5;
    var a = {
        start: {
            x: 0 - this.view_port.width * this.sanity,
            y: 0 - this.view_port.height * this.sanity
        },
        end: {
            x: this.view_port.width + this.view_port.width * this.sanity,
            y: this.view_port.height + this.view_port.height * this.sanity
        },
        cell: {
            width: this.view_port.cell.width,
            height: this.view_port.cell.height
        }
    };
    return a
};
GmapsMarkerManager.prototype.buildGrid = function(d) {
    var b = new Array();
    for (var c = d.start.x; c < d.end.x; c += d.cell.width) {
        for (var a = d.start.y; a < d.end.y; a += d.cell.height) {
            b.push(new google.maps.LatLngBounds(this.getProjection().fromDivPixelToLatLng(new google.maps.Point(c, a + d.cell.height)), this.getProjection().fromDivPixelToLatLng(new google.maps.Point(c + d.cell.width, a))))
        }
    }
    return b
};
GmapsMarkerManager.prototype.checkMarkers = function(d, b) {
    for (var c = 0; c < b.length; c++) {
        this.view_port.markers[c].count = 0;
        this.view_port.markers[c].items = new Array();
        this.view_port.markers[c].bounds = b[c];
        for (var a = 0; a < d.length; a++) {
            if (b[c].contains(d[a].getPosition())) {
                this.view_port.markers[c].count++;
                this.view_port.markers[c].items.push(d[a])
            }
        }
    }
    return true
};
GmapsMarkerManager.prototype.groupMarkers = function() {
    this.threshold = this.map.getZoom() >= this.threshold_zoom ? true: false;
    var b = b || new google.maps.InfoWindow();
    for (var c = 0; c < this.view_port.markers.length; c++) {
        if (this.view_port.markers[c].count && !this.view_port.markers[c].alias) {
            me = this;
            if (this.threshold) {
                for (var a = 0; a < this.view_port.markers[c].items.length; a++) {
                    this.view_port.markers[c].items[a].setMap(this.map);
                    google.maps.event.addListener(this.view_port.markers[c].items[a], "click",
                    function() {
                        if (me.markers_infowindows[c]) {
                            b.setContent(this.markers_infowindows[c]);
                            b.open(me.map, this)
                        }
                    })
                }
            } else {
                for (var a = 0; a < this.view_port.markers[c].items.length; a++) {
                    this.view_port.markers[c].items[a].setMap(null)
                }
                if (this.view_port.markers[c].count == 1) {
                    this.view_port.markers[c].alias = this.view_port.markers[c].items[0];
                    this.view_port.markers[c].alias.setMap(this.map);
                    google.maps.event.addListener(this.view_port.markers[c].alias, "click",
                    function() {
                        if (me.markers_infowindows[c]) {
                            b.setContent(this.markers_infowindows[c]);
                            b.open(me.map, this)
                        }
                    })
                } else {
                    this.view_port.markers[c].alias = new google.maps.Marker({
                        position: this.view_port.markers[c].items[0].getPosition(),
                        title: this.view_port.markers[c].count.toString()
                    });
					
                    if (this.group_icon_src) {
                        this.view_port.markers[c].alias.setIcon(new google.maps.MarkerImage(this.group_icon_src))
                    }
                    if (this.group_icon_shadow) {
                        this.view_port.markers[c].alias.setShadow(new google.maps.MarkerImage(this.group_icon_shadow))
                    }
                    this.view_port.markers[c].alias.setMap(this.map)
                }
            }
        }
    }
};
