text: 'use strict';
  
  //
  // Utils for testing.
  //
  
  var mongo = require('mongodb');
  var MongoClient = mongo.MongoClient;
  var request = require('request');
  var Q = require('q');
  var connection = require('../lib/helpers/connection');
  
  //
  // Drop the specified test database.
  //
  var dropDatabase = function (testDbName) {
      var db = null;
  
      return MongoClient.connect('mongodb://localhost:27017/' + testDbName)
          .then(dbConn => (db = dbConn) && db.dropDatabase())
          .then(() => db.close());
  };
  
  //
  // Save a document and return a promise.
  var saveDocument = function (collection, document) {
      var deferred = Q.defer();
      collection.save(document, function (err, doc) {
          if (err) {
              deferred.reject(err);
          }
          else {
              deferred.resolve(doc);
          }
      });
  
      return deferred.promise;
  };
  
  //
  // Load data into a db collection.
  //
  var loadFixture = function (testDbName, testCollectionName, data) {
      var db = null;
  
      return MongoClient.connect('mongodb://localhost:27017/' + testDbName)
          .then(dbConn => (db = dbConn) && db.createCollection(testCollectionName))
          .then(function (collection) {
              return Q.all(data.map(function (dataItem) {
                  return saveDocument(collection, dataItem);
              }));
          })
          .then(() => db.close());
  };
  
  //
  // Load data into a db collection.
  //
  var dropDatabaseAndLoadFixture = function (testDbName, testCollectionName, data) {
      return dropDatabase(testDbName)
          .then(function () {
              return loadFixture(testDbName, testCollectionName, data);
          });
  };
  
  //
  // Request http document from the rest api.
  //
  var requestHttp = function (url) {
      var deferred = Q.defer();
  
      request(url, function (err, response, body) {
  
          if (err) {
              deferred.reject(err);
              return;
          }
  
          deferred.resolve({
              data: body,
              response: response,
          });
      });
  
      return deferred.promise;
  };
  
  //
  // Request JSON from the rest api.
  //
  var requestJson = function (url) {
      var deferred = Q.defer();
  
      request(url, function (err, response, body) {
          if (err) {
              deferred.reject(err);
              return;
          }
  
          deferred.resolve({
              data: JSON.parse(body),
              response: response,
          });
      });
  
      return deferred.promise;
  };
  
  //
  // Get a collection and run expectations on it.
  //
  var collectionJson = function (url) {
      return requestJson(url);
  };
  
  //
  // Get an item from the db and run expectations on it.
  //
  var itemJson = function (collectionUrl, itemID) {
      var itemUrl = collectionUrl + "/" + itemID.toString();
      return requestJson(itemUrl);
  };
  
  //
  // Get the response for a db item.
  //
  var itemHttp = function (collectionUrl, itemID) {
      var itemUrl = collectionUrl + "/" + itemID.toString();
      return requestHttp(itemUrl);
  };
  
  //
  // Invoke a HTTP PUT.
  //
  var post = function (url, data) {
      var deferred = Q.defer();
  
      request.post({
              url: url,
              json: true,
              body: data,
          },
          function (err, response, body) {
              if (err) {
                  deferred.reject(err);
                  return;
              }
  
              deferred.resolve({
                  data: body,
                  response: response,
              });
          }
      );
  
      return deferred.promise;
  };
  
  //
  // Invoke a HTTP PATCH.
  //
  var patch = function (collectionUrl, itemID, data) {
      var deferred = Q.defer();
      var itemUrl = collectionUrl + "/" + itemID.toString();
  
      request.patch({
          url: itemUrl,
          json: data,
      }, function (err, response, body) {
          if (err) {
              deferred.reject(err);
          }
          else {
              deferred.resolve({
                  data: body,
                  response: response,
              });
          }
      });
  
      return deferred.promise;
  };
  
  //
  // Invoke a HTTP PUT.
  //
  var put = function (collectionUrl, itemID, data) {
      var deferred = Q.defer();
      var itemUrl = collectionUrl + "/" + itemID.toString();
      request.put({
          url: itemUrl,
          json: data,
      }, function (err, response, body) {
  
          if (err) {
              deferred.reject(err);
          }
          else {
              deferred.resolve({
                  data: body,
                  response: response,
              });
          }
      });
      return deferred.promise;
  };
  
  //
  // Inovke a HTTP DELETE.
  //
  var del = function (collectionUrl, itemID) {
      var deferred = Q.defer();
      var itemUrl = collectionUrl + "/" + itemID.toString();
      request.del({
          url: itemUrl,
      }, function (err, response, body) {
  
          if (err) {
              deferred.reject(err);
          }
          else {
              deferred.resolve({
                  data: body,
                  response: response,
              });
          }
      });
      return deferred.promise;
  };
  
  var nextCollectionNumber = 1;
  var nextDbNumber = 1;
  var url = 'http://localhost:3000/';
  var dbsUrl = url + 'dbs';
  
  var restServer = require('../server');
  
  module.exports = {
      dropDatabaseAndLoadFixture: dropDatabaseAndLoadFixture,
      dropDatabase: dropDatabase,
      loadFixture: loadFixture,
      requestHttp: requestHttp,
      requestJson: requestJson,
      collectionJson: collectionJson,
      itemJson: itemJson,
      itemHttp: itemHttp,
      post: post,
      put: put,
      del: del,
      patch: patch,
  
      // Start the rest server.
      startServer: function (config) {
          var deferred = Q.defer();
  
          // Open the rest server for each test.
          restServer.startServer(config, function (err) {
              if (err) {
                  deferred.reject(err);
              }
              else {
                  deferred.resolve();
              }
          });
  
          return deferred.promise;
      },
  
      stopServer: function () {
          restServer.stopServer();
          connection.closeAll();
      },
  
      genDbsUrl: function () {
          return dbsUrl;
      },
  
      genTestDbName: function () {
          return 'mongodb_rest_test' + nextDbNumber++;
      },
  
      genTestCollectionName: function () {
          return 'mongodb_test_collection' + nextCollectionNumber++;
      },
  
      genCollectionsUrl: function (dbName) {
          return url + dbName;
      },
  
      genCollectionUrl: function (dbName, collectionName) {
          return this.genCollectionsUrl(dbName) + '/' + collectionName;
      },
  
      genBulkUrl: function (dbName) {
          return this.genCollectionsUrl(dbName) + '/bulk';
      },
  
      genBulkUrlDatabaseEndpoint: function () {
          return this.genCollectionsUrlDatabaseEndpoint() + 'bulk';
      },
  
      genCollectionsUrlDatabaseEndpoint: function () {
          return url;
      },
  
      genCollectionUrlDatabaseEndpoint: function (collectionName) {
          return this.genCollectionsUrlDatabaseEndpoint() + collectionName;
      },
  
  };
  
  