/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* 
*/
'use strict';












const BaseReporter = require('./BaseReporter');var _require =

require('istanbul-api');const createReporter = _require.createReporter;
const chalk = require('chalk');
const fs = require('fs');
const generateEmptyCoverage = require('../generateEmptyCoverage');
const istanbulCoverage = require('istanbul-lib-coverage');

const COVERAGE_SUMMARY = chalk.bold;
const FAIL_COLOR = chalk.bold.red;
const RUNNING_TEST_COLOR = chalk.bold.dim;

class CoverageReporter extends BaseReporter {


  constructor() {
    super();
    this._coverageMap = istanbulCoverage.createCoverageMap({});
  }

  onTestResult(
  config,
  testResult,
  aggregatedResults)
  {
    if (testResult.coverage) {
      this._coverageMap.merge(testResult.coverage);
    }
  }

  onRunComplete(
  config,
  aggregatedResults,
  runnerContext)
  {
    this._addUntestedFiles(config, runnerContext);
    const reporter = createReporter();
    try {
      if (config.coverageDirectory) {
        reporter.dir = config.coverageDirectory;
      }
      reporter.addAll(config.coverageReporters || []);
      reporter.write(this._coverageMap);

      if (
      config.coverageReporters &&
      config.coverageReporters.length &&
      config.coverageReporters.indexOf('text') === -1)
      {
        const results = this._coverageMap.getCoverageSummary().toJSON();
        const format = percent => percent + (percent === 'Unknown' ? '' : '%');
        this.log(
        '\n' + COVERAGE_SUMMARY('Coverage Summary') + ' (add "text" to the ' +
        '"coverageReporters" setting to receive a full report)\n' +
        ' \u203A Statements: ' + format(results.statements.pct) + '\n' +
        ' \u203A Branches: ' + format(results.branches.pct) + '\n' +
        ' \u203A Lines: ' + format(results.lines.pct) + '\n' +
        ' \u203A Functions: ' + format(results.functions.pct) + '\n');

      }
    } catch (e) {
      console.error(chalk.red(`
        Failed to write coverage reports:
        ERROR: ${ e.toString() }
        STACK: ${ e.stack }
      `));
    }

    this._checkThreshold(config);
  }

  _addUntestedFiles(config, runnerContext) {
    if (config.collectCoverageFrom && config.collectCoverageFrom.length) {
      process.stderr.write(RUNNING_TEST_COLOR(
      'Running coverage on untested files...'));

      const files = runnerContext.hasteFS.matchFilesWithGlob(
      config.collectCoverageFrom,
      config.rootDir);


      files.forEach(filename => {
        if (!this._coverageMap.data[filename]) {
          try {
            const source = fs.readFileSync(filename).toString();
            const coverage = generateEmptyCoverage(source, filename, config);
            if (coverage) {
              this._coverageMap.addFileCoverage(coverage);
            }
          } catch (e) {
            console.error(chalk.red(`
              Failed to collect coverage from ${ filename }
              ERROR: ${ e }
              STACK: ${ e.stack }
            `));
          }
        }
      });
      this.clearLine();
    }
  }

  _checkThreshold(config) {
    if (config.coverageThreshold) {
      const results = this._coverageMap.getCoverageSummary().toJSON();

      function check(name, thresholds, actuals) {
        return [
        'statements',
        'branches',
        'lines',
        'functions'].
        reduce((errors, key) => {
          const actual = actuals[key].pct;
          const actualUncovered = actuals[key].total - actuals[key].covered;
          const threshold = thresholds[key];

          if (threshold != null) {
            if (threshold < 0) {
              if (threshold * -1 < actualUncovered) {
                errors.push(
                `Jest: Uncovered count for ${ key } (${ actualUncovered })` +
                `exceeds ${ name } threshold (${ -1 * threshold })`);

              }
            } else if (actual < threshold) {
              errors.push(
              `Jest: Coverage for ${ key } (${ actual }` +
              `%) does not meet ${ name } threshold (${ threshold }%)`);

            }
          }
          return errors;
        }, []);
      }
      const errors = check(
      'global',
      config.coverageThreshold.global,
      results);


      if (errors.length > 0) {
        this.log(`${ FAIL_COLOR(errors.join('\n')) }`);
        this._setError(new Error(errors.join('\n')));
      }
    }
  }

  // Only exposed for the internal runner. Should not be used
  getCoverageMap() {
    return this._coverageMap;
  }}


module.exports = CoverageReporter;