text: 'use strict';
  const setupDatabase = require('./shared').setupDatabase;
  const expect = require('chai').expect;
  const MongoClient = require('../../index').MongoClient;
  const ReadPreference = require('../../index').ReadPreference;
  const Logger = require('../../index').Logger;
  
  describe('Sharding (Read Preference)', function() {
    before(function() {
      return setupDatabase(this.configuration);
    });
  
    /**
     * @ignore
     */
    it.skip('Should correctly perform a Mongos secondary read using the read preferences', {
      metadata: { requires: { topology: 'sharded' } },
  
      // The actual test we wish to run
      test: function(done) {
        // NOTE: this test is skipped because it directly mucks with the connection string, which isn't
        // guaranteed to be present with mongo-orchestration. This behavior should be unit tested.
  
        const configuration = this.configuration;
        const host = configuration.host;
        const port = configuration.port;
  
        const url = `mongodb://${host}:${port}/sharded_test_db?w=1`;
        // Connect using the mongos connections
        var client = new MongoClient(url, { w: 0, monitorCommands: true });
        client.connect(function(err) {
          expect(err).to.not.exist;
          const db = client.db(configuration.db);
  
          // Perform a simple insert into a collection
          const collection = db.collection('shard_test1');
          // Insert a simple doc
          collection.insertOne({ test: 1 }, { w: 'majority', wtimeout: 10000 }, function(err) {
            expect(err).to.not.exist;
  
            // Set debug level for the driver
            Logger.setLevel('debug');
  
            let gotMessage = false;
  
            // Get the current logger
            Logger.setCurrentLogger(function(message, options) {
              if (
                options.type === 'debug' &&
                options.className === 'Cursor' &&
                options.message.indexOf('"mode":"secondary"') !== -1
              ) {
                gotMessage = true;
              }
            });
  
            collection.findOne(
              { test: 1 },
              { readPreference: new ReadPreference(ReadPreference.SECONDARY) },
              function(err, item) {
                expect(err).to.not.exist;
                expect(item).to.exist.and.to.have.property('test', 1);
                expect(gotMessage).to.equal(true);
  
                // Set error level for the driver
                Logger.setLevel('error');
                // Close db connection
                client.close(done);
              }
            );
          });
        });
      }
    });
  
    /**
     * @ignore
     */
    it('Should fail a Mongos secondary read using the read preference and tags that dont exist', {
      metadata: { requires: { topology: 'sharded' } },
  
      // The actual test we wish to run
      test: function(done) {
        const configuration = this.configuration;
        const host = configuration.host;
        const port = configuration.port;
  
        const url = `mongodb://${host}:${port}/sharded_test_db?w=1`;
        // Connect using the mongos connections
        const client = new MongoClient(url, { w: 0 });
        client.connect(function(err) {
          expect(err).to.not.exist;
          const db = client.db(configuration.db);
  
          // Perform a simple insert into a collection
          const collection = db.collection('shard_test3');
          // Insert a simple doc
          collection.insertOne({ test: 1 }, { w: 'majority', wtimeout: 10000 }, function(err) {
            expect(err).to.not.exist;
  
            // Set debug level for the driver
            Logger.setLevel('debug');
  
            let gotMessage = false;
            // Get the current logger
            Logger.setCurrentLogger(function(message, options) {
              if (
                options.type === 'debug' &&
                options.className === 'Cursor' &&
                options.message.indexOf(
                  '{"mode":"secondary","tags":[{"dc":"sf","s":"1"},{"dc":"ma","s":"2"}]}'
                ) !== -1
              ) {
                gotMessage = true;
              }
            });
  
            collection.findOne(
              { test: 1 },
              {
                readPreference: new ReadPreference(ReadPreference.SECONDARY, [
                  { dc: 'sf', s: '1' },
                  { dc: 'ma', s: '2' }
                ])
              },
              function(err) {
                expect(err).to.exist;
                expect(gotMessage).to.equal(true);
                // Set error level for the driver
                Logger.setLevel('error');
                // Close db connection
                client.close(done);
              }
            );
          });
        });
      }
    });
  
    /**
     * @ignore
     */
    it.skip('Should correctly read from a tagged secondary using Mongos', {
      // NOTE: skipped because mongo-orchestration will not set up these tags
      metadata: { requires: { topology: 'sharded' } },
  
      // The actual test we wish to run
      test: function(done) {
        const configuration = this.configuration;
        // Set up mongos connection
  
        // Connect using the mongos connections
        const client = new MongoClient(configuration.url(), { w: 0 });
        client.connect(function(err) {
          expect(err).to.not.exist;
          const db = client.db(configuration.db);
  
          // Perform a simple insert into a collection
          const collection = db.collection('shard_test4');
          // Insert a simple doc
          collection.insertOne({ test: 1 }, { w: 'majority', wtimeout: 10000 }, function(err) {
            expect(err).to.not.exist;
  
            // Set debug level for the driver
            Logger.setLevel('debug');
  
            let gotMessage = false;
            // Get the current logger
            Logger.setCurrentLogger(function(message, options) {
              if (
                options.type === 'debug' &&
                options.className === 'Cursor' &&
                options.message.indexOf('{"mode":"secondary","tags":[{"loc":"ny"},{"loc":"sf"}]}') !==
                  -1
              ) {
                gotMessage = true;
              }
            });
  
            collection.findOne(
              { test: 1 },
              {
                readPreference: new ReadPreference(ReadPreference.SECONDARY, [
                  { loc: 'ny' },
                  { loc: 'sf' }
                ])
              },
              function(err, item) {
                expect(err).to.not.exist;
                expect(item).to.exist.and.to.have.a.property('test', 1);
                expect(gotMessage).to.equal(true);
                // Set error level for the driver
                Logger.setLevel('error');
                // Close db connection
                client.close(done);
              }
            );
          });
        });
      }
    });
  
    /**
     *
     * @ignore
     */
    it('shouldCorrectlyEmitOpenEvent', {
      metadata: { requires: { topology: 'sharded' } },
  
      // The actual test we wish to run
      test: function(done) {
        const configuration = this.configuration;
  
        let openCalled = false;
  
        const client = new MongoClient(configuration.url(), { w: 0 });
        client.once('open', () => (openCalled = true));
  
        client.connect(function(err, client) {
          expect(err).to.not.exist;
          expect(client).to.exist;
          expect(openCalled).to.equal(true);
  
          client.close(done);
        });
      }
    });
  
    /**
     *
     * @ignore
     */
    it('Should correctly apply readPreference when performing inline mapReduce', {
      metadata: { requires: { topology: 'sharded' } },
  
      // The actual test we wish to run
      test: function(done) {
        const configuration = this.configuration;
  
        // Connect using the mongos connections
        const client = new MongoClient(configuration.url());
        client.connect(function(err) {
          expect(err).to.not.exist;
          const db = client.db(configuration.db);
  
          // Get the collection
          const col = db.collection('items');
          // Insert some items
          col.insertMany([{ a: 1 }, { a: 2 }, { a: 3 }], function(err) {
            expect(err).to.not.exist;
  
            client.db('admin').command({ enableSharding: 'integration_test_2' }, function(err) {
              expect(err).to.not.exist;
  
              col.createIndex({ _id: 'hashed' }, function(err) {
                expect(err).to.not.exist;
  
                client.db('admin').command(
                  {
                    shardCollection: 'integration_test_2.items',
                    key: { _id: 'hashed' }
                  },
                  function(err) {
                    expect(err).to.not.exist;
  
                    var map = function() {
                      emit(this._id, this._id); // eslint-disable-line
                    };
  
                    var reduce = function() {
                      return 123;
                    };
  
                    col.mapReduce(
                      map,
                      reduce,
                      {
                        out: {
                          inline: 1
                        },
                        readPreference: ReadPreference.SECONDARY_PREFERRED
                      },
                      function(err, r) {
                        expect(err).to.not.exist;
                        expect(r).to.have.a.lengthOf(3);
                        client.close(done);
                      }
                    );
                  }
                );
              });
            });
          });
        });
      }
    });
  });
  