var RBTree = require('bintrees').RBTree
var hash = require('hash.murmur3.32')
var fnv = require('hash.fnv')
var monotonic = require('monotonic')

function Router (options) {
    this.routes = []
    this.distribute(options.delegates, 256, options.version || 0) // switch to
    //monotonic
    this.extract = options.extract
    this.incrementVersion = options.incrementVersion || function (x) {
        //return  x + 1
        console.log(x)
        return monotonic.increment(x)
    }
    this.connections = [ this.connectionTable(options.version || 0xffffffff) ]
}

Router.prototype.connectionTable = function (version) {
    return { // switch to monotonic
        version: monotonic.parse(version.toString()),
        connections: new RBTree(function (a, b) {
            a = this.extract(a)
            b = this.extract(b)
            return a < b ? -1 : a > b ? 1 : 0
        }.bind(this))
    }
}

Router.prototype.match = function (obj) {
    var key = this.extract(obj)
    return this.routes[0].buckets[fnv(0, new Buffer(key), 0,
    Buffer.byteLength(key)) & 0xFF].url
}

Router.prototype.distribute = function (delegates, length, version) {
    var dist = Math.floor(length / delegates.length)
    var buckets = []
    delegates.forEach(function (del) {
        for (var i = 0; i < dist; i++) {
            length--
            buckets.push({
                url: del
            })
        }
    }, this)
    while (length-- > 0) {
        buckets.push({ url: delegates[delegates.length - 1] })
    }

    this.routes.unshift({
        buckets: buckets,
        delegates: delegates,
        version: monotonic.parse(version.toString())
    })
}

Router.prototype.add = function (delegate) {
    var delegates = this.routes[0].delegates.slice(),
    buckets = this.routes[0].buckets.slice(),
    redist = Array.apply(null, Array(delegates.length)).map(Number.prototype.valueOf, 0)
    delegates.push(delegate)

    var dist = Math.floor(buckets.length / delegates.length)
    dist = Math.floor(dist / (delegates.length - 1))

    for (var b = 0, I = buckets.length; b < I; b++) {
        if (redist[delegates.indexOf(buckets[b].url)] == dist) continue
        redist[delegates.indexOf(buckets[b].url)] += 1
        buckets[b].url = delegate
    }

    this.routes.unshift({
        buckets: buckets,
        delegates: delegates,
        version : this.incrementVersion(this.routes[0].version)
    })
}

Router.prototype.remove = function (delegate) {
    var delegates = this.routes[0].delegates.slice(),
    buckets = this.routes[0].buckets.slice(), indices = []
    delegates = delegates.splice(delegates.indexOf(delegate), 1)

    for (var b = 0, I = buckets.length; b < I; b++) {
        if (this.routes[0].buckets[b].url == delegate) {
            indices.push(b)
        }
    }

    var dist = Math.floor(indices.length, this.routes[0].delegates.length - 1)

    for (var b = 0, I = indices.length; b < I; b++) {
        for (var i=0; i<dist; i++) {
            buckets[indices[b]].url = delegates[i]
        }
    }

    this.routes.unshift({
        buckets: buckets,
        delegates: delegates,
        version: this.incrementVersion(this.routes[0].version)
    })
}

Router.prototype.addConnection = function (version, connection) {
    if (version > this.connections[0].version) {
        this.connections.unshift(this.connectionTable(version))
    }
    if (!this.connections[0].connections.insert(connection)) {
        //trouble
    }
}

Router.prototype.removeConnection = function (version, connection) {
    if (version > this.connections[0].version) {
        this.connections.unshift(this.connectionTable(version))
    } else if (!this.connections[0].connections.remove(connection)) {
        //trouble
    }
}

Router.prototype.evictable = function (latest, delegate, inspect) {
    var version, old = this.connections.length
    while (old--) {
        this.connections[old].connections.each(function (conn) {
            if (delegate == this.match(conn)) {
                return conn
            }
        })
    }
}


exports.Router = Router

@@ -1217,24 +1217,25 @@
 uckets = %5B%5D%0A
+%0A
     delegate
@@ -1413,16 +1413,17 @@
 , this)%0A
+%0A
     whil
@@ -3545,128 +3545,8 @@
  if 
-(version %3E this.connections%5B0%5D.version) %7B%0A        this.connections.unshift(this.connectionTable(version))%0A    %7D else if 
 (!th

Fix `removeConnection`.