var cont      = require('cont')
var deepEqual = require('deep-equal')
var tape      = require('tape')
var ssbKeys   = require('ssb-keys')
var crypto    = require('crypto')

var u = require('./util')

// create 3 servers
// give them all pub servers (on localhost)
// and get them to follow each other...

var createSsbServer = require('secret-stack')({
    caps: {shs: crypto.randomBytes(32).toString('base64')}
  })
  .use(require('ssb-db'))
  .use(require('ssb-replicate'))
  .use(require('..'))
  .use(require('ssb-friends'))
  .use(require('ssb-gossip'))

tape('replicate between 3 peers', function (t) {

  var alice, bob, carol
  var dbA = createSsbServer({
    temp: 'server-alice',
    port: 45451, timeout: 1400,
    keys: alice = ssbKeys.generate(),
    replicate: {legacy: false},
    gossip: {pub: false},
    level: 'info'
  })
  var dbB = createSsbServer({
    temp: 'server-bob',
    port: 45452, timeout: 1400,
    keys: bob = ssbKeys.generate(),
    seeds: [dbA.getAddress()],
    replicate: {legacy: false},
    gossip: {pub: false},
    level: 'info'
  })
  var dbC = createSsbServer({
    temp: 'server-carol',
    port: 45453, timeout: 1400,
    keys: carol = ssbKeys.generate(),
    seeds: [dbA.getAddress()],
    replicate: {legacy: false},
    gossip: {pub: false},
    level: 'info'
  })

  var apub = cont(dbA.publish)
  var bpub = cont(dbB.publish)
  var cpub = cont(dbC.publish)

  cont.para([
    apub(u.pub(dbA.getAddress())),
    bpub(u.pub(dbB.getAddress())),
    cpub(u.pub(dbC.getAddress())),

    apub(u.follow(bob.id)),
    apub(u.follow(carol.id)),

    bpub(u.follow(alice.id)),
    bpub(u.follow(carol.id)),

    cpub(u.follow(alice.id)),
    cpub(u.follow(bob.id))
  ]) (function (err, ary) {
    if(err) throw err

    var expected = {}
    expected[alice.id] = expected[bob.id] = expected[carol.id] = 3
    function check(server, name) {
      var closed = false
      var int = setInterval(function () {
        server.getVectorClock(function (err, actual) {
          if(err) throw err
          if(closed) return
          console.log(actual)
          if(deepEqual(expected, actual)) {
            clearInterval(int)
            closed = true
            done()
          }
        })
      }, 1000)
    }

    check(dbA, 'ALICE')
    check(dbB, 'BOB')
    check(dbC, 'CAROL')

    var n = 3

    function done () {
      if(--n) return
      dbA.close(true); dbB.close(true); dbC.close(true)
      t.ok(true)
      t.end()
    }
  })
})
