'use strict';

module.exports = function (PouchDB, Promise) {

  var NUM_DOCS = 1000;
  var MAX_SOCKETS = 15;
  var BATCH_SIZE = 100;

  var commonUtils = require('../common-utils.js');
  var log = require('debug')('pouchdb:tests:performance');

  var PullRequestTestObject = function () {
    this.localPouches = [];
  };

  PullRequestTestObject.prototype.setup = function (itr, gens) {
    var self = this;
    return function (localDB, _, callback) {
      var remoteDBOpts = {ajax: {pool: {maxSockets: MAX_SOCKETS}}};
      var remoteCouchUrl = commonUtils.couchHost() + "/" +
        commonUtils.safeRandomDBName();

      self.remoteDB = new PouchDB(remoteCouchUrl, remoteDBOpts);

      var i;
      var docs = [];
      var localOpts = {ajax: {timeout: 60 * 1000}};

      for (i = 0; i < itr; ++i) {
        self.localPouches[i] = new PouchDB(commonUtils.safeRandomDBName());
      }

      for (i = 0; i < NUM_DOCS; i++) {
        docs.push({
          _id: commonUtils.createDocId(i),
          foo: Math.random(),
          bar: Math.random()
        });
      }

      var addGeneration = function (generationCount, docs) {
        return self.remoteDB.bulkDocs({docs}, localOpts)
          .then(function (bulkDocsResponse) {
            --generationCount;
            if (generationCount <= 0) {
              return {};
            }
            var updatedDocs = bulkDocsResponse.map(function (doc) {
              return {
                _id: doc.id,
                _rev: doc.rev,
                foo: Math.random(),
                bar: Math.random()
              };
            });
            return addGeneration(generationCount, updatedDocs);
          });
      };

      return addGeneration(gens, docs).then(function (/* result */) {
        callback();
      }).catch(callback);
    };
  };

  PullRequestTestObject.prototype.test = function () {
    var self = this;
    return function (ignoreDB, itr, ignoreContext, done) {
      var localDB = self.localPouches[itr];
      PouchDB.replicate(self.remoteDB, localDB,
        {live: false, batch_size: BATCH_SIZE})
      .on('change', function (info) {
        log("replication - info - " + JSON.stringify(info));
      })
      .on('complete', function (info) {
        log("replication - complete - " + JSON.stringify(info));
        done();
      })
      .on('error', function (err) {
        log("replication - error - " + JSON.stringify(err));
        throw err;
      });
    };
  };

  PullRequestTestObject.prototype.tearDown = function () {
    var self = this;
    return function () {
      return self.remoteDB.destroy().then(function () {
        return Promise.all(
          self.localPouches.map(function (localPouch) {
            return localPouch.destroy();
          }));
      });
    };
  };

  return PullRequestTestObject;
};
