text: const Test = require('./test');
  const async = require('async');
  const fs = require('fs-extra');
  const File = require('./../core/file');
  const remixTests = require('remix-tests');
  const Base = require('mocha/lib/reporters/base');
  const color = Base.color;
  
  class SolcTest extends Test {
    constructor(options) {
      super(options);
      this.assertLibCode = remixTests.assertLibCode;
    }
    init(cb) {
      const self = this;
      super.init(() => {
        let assertFile = new File({
          filename: 'remix_tests.sol',
          type: File.types.custom,
          path: 'remix_tests.sol',
          resolver: (callback) => {
            callback(self.assertLibCode);
          }});
        self.engine.config.contractsFiles.push(assertFile);
        cb();
      });
    }
    setupTests(files, cb) {
      const self = this;
      files.forEach((file) => {
        let testFile = self._prepareContractForTest(file);
        self.engine.config.contractsFiles.push(new File({filename: file, type: File.types.custom, path: file, resolver: function (callback) {
          callback(testFile);
        }}));
      });
  
      async.waterfall([
        function initWeb3Provider(next) {
          self.initWeb3Provider(next);
        },
        function resetContracts(next) {
          self.engine.events.request("contracts:reset:dependencies", next);
        },
        function compile(next) {
          console.info('Compiling contracts'.cyan);
          self.engine.events.request("contracts:build", false, next);
        },
        function determineContractsToDeploy(next) {
          self.engine.events.request("contracts:list", (err, contracts) => {
            let contractsToDeploy = contracts.filter((contract) => contract.filename.indexOf('_test.sol') >=0);
            let assertLib = contracts.filter((contract) => contract.filename === 'remix_tests.sol')[0];
            next(null, [assertLib].concat(contractsToDeploy));
          });
        },
        function deployContracts(contracts, next) {
          console.info('Deploying contracts'.cyan);
          let fns = [];
          contracts.forEach((contract) => {
            contract._gasLimit = self.gasLimit;
            let fn = (cb) => {
              self.engine.events.request('deploy:contract', contract, cb);
            };
            fns.push(fn);
          });
          async.series(fns, next);
        }
      ],cb);
    }
    runTests(file, cb) {
      console.info('Running tests'.cyan);
      const self = this;
      self.engine.events.request('contracts:all', (err, contracts) => {
        let contractsToTest = [];
        Object.keys(contracts).forEach((contract) => {
          if(contracts[contract].filename === file) {
            contractsToTest.push(contracts[contract]);
          }
        });
        let fns = [];
        contractsToTest.forEach((contract) => {
          let contractObject = self._convertToWeb3(contract);
          let fn = (_callback) => {
            // TODO: web3 is not injected into the function. Issue has been raised on remixTests.
            // To fix once web3 has been made injectable.
            remixTests.runTest(contract.className, contractObject, self._prettyPrint.bind(self), _callback);
          };
          fns.push(fn);
        });
        async.series(fns, cb);
      });
    }
    _convertToWeb3(contract) {
      let contractObject = new this.web3.eth.Contract(contract.abiDefinition);
      contractObject.options.address = contract.deployedAddress;
      contractObject.options.from = contract.deploymentAccount;
      contractObject.options.gas = contract.gas;
      contractObject.filename = contract.filename;
      return contractObject;
    }
    // dynamically insert Assert library as an import
    // regexIndexOf has been added to String's prototype in remix-tests module
    _prepareContractForTest(file) {
      let c = fs.readFileSync(file).toString();
      const s = /^(import)\s['"](remix_tests.sol)['"];/gm;
      if (c.regexIndexOf(s) < 0) {
        c = c.replace(/(pragma solidity \^\d+\.\d+\.\d+;)/, '$1\nimport \"remix_tests.sol\";');
      }
      return c;
    }
  
    _prettyPrint(obj) {
      if (obj.type === 'contract') {
        console.log(color('suite', '%s'), obj.value);
      } else if(obj.type === 'testPass') {
        let fmt = color('checkmark', '  ' + Base.symbols.ok) + color('pass', ' %s');
        console.log(fmt, obj.value);
      } else if(obj.type === 'testFailure') {
        let fmt = color('fail', '  %s %s');
        console.log(fmt, Base.symbols.err, obj.value);
      }
    }
  }
  
  module.exports = SolcTest;
  