const istanbul = require('istanbul-api');
const util = require('./util');

const BROWSER_PLACEHOLDER = '%browser%';

function checkThresholds(thresholds, summary) {
  const failedTypes = [];

  Object.keys(thresholds).forEach(key => {
    const coverage = summary[key].pct;
    if (coverage < thresholds[key]) {
      failedTypes.push(key);
    }
  });

  return failedTypes;
}

function CoverageIstanbulReporter(baseReporterDecorator, logger, config) {
  baseReporterDecorator(this);

  // Copied from https://github.com/angular/angular-cli/pull/9529/files
  // Fixes https://github.com/mattlewis92/karma-coverage-istanbul-reporter/issues/44
  const reporterName = 'coverage-istanbul';
  const hasTrailingReporters =
    config.reporters.slice(-1).pop() !== reporterName;
  if (hasTrailingReporters) {
    this.writeCommonMsg = () => {};
  }

  const log = logger.create('reporter.coverage-istanbul');
  const browserCoverage = new WeakMap();
  const coverageConfig = Object.assign({}, config.coverageIstanbulReporter);

  function addCoverage(coverageMap, browser) {
    const coverage = browserCoverage.get(browser);
    browserCoverage.delete(browser);

    if (!coverage) {
      return;
    }

    Object.keys(coverage).forEach(filename => {
      const fileCoverage = coverage[filename];
      if (fileCoverage.inputSourceMap && coverageConfig.fixWebpackSourcePaths) {
        fileCoverage.inputSourceMap = util.fixWebpackSourcePaths(
          fileCoverage.inputSourceMap,
          config.webpack
        );
      }

      if (
        coverageConfig.skipFilesWithNoCoverage &&
        Object.keys(fileCoverage.statementMap).length === 0 &&
        Object.keys(fileCoverage.fnMap).length === 0 &&
        Object.keys(fileCoverage.branchMap).length === 0
      ) {
        log.debug(`File [${filename}] ignored, nothing could be mapped`);
      } else {
        coverageMap.addFileCoverage(fileCoverage);
      }
    });
  }

  function logThresholdMessage(thresholds, message) {
    if (thresholds.emitWarning) {
      log.warn(message);
    } else {
      log.error(message);
    }
  }

  function createReport(browserOrBrowsers, results) {
    const reportConfigOverride =
      !coverageConfig.combineBrowserReports && coverageConfig.dir
        ? {
            dir: coverageConfig.dir.replace(
              BROWSER_PLACEHOLDER,
              browserOrBrowsers.name
            )
          }
        : {};

    const reportConfig = istanbul.config.loadObject({
      instrumentation: Object.assign({}, coverageConfig.instrumentation),
      verbose: coverageConfig.verbose === true,
      reporting: Object.assign({}, coverageConfig, reportConfigOverride)
    });
    const reportTypes = reportConfig.reporting.config.reports;

    const reporter = istanbul.createReporter(reportConfig);
    reporter.addAll(reportTypes);

    const coverageMap = istanbul.libCoverage.createCoverageMap();
    const sourceMapStore = istanbul.libSourceMaps.createSourceMapStore();

    if (coverageConfig.combineBrowserReports) {
      browserOrBrowsers.forEach(browser => addCoverage(coverageMap, browser));
    } else {
      addCoverage(coverageMap, browserOrBrowsers);
    }

    const {
      sourceFinder,
      map: remappedCoverageMap
    } = sourceMapStore.transformCoverage(coverageMap);

    if (!coverageConfig.skipFilesWithNoCoverage) {
      // On Windows, istanbul returns files with mixed forward/backslashes in them
      const fixedFilePaths = {};
      remappedCoverageMap.files().forEach(path => {
        fixedFilePaths[util.fixPathSeparators(path)] = true;
      });
      coverageMap.files().forEach(path => {
        if (!(util.fixPathSeparators(path) in fixedFilePaths)) {
          // Re-add empty coverage record
          remappedCoverageMap.addFileCoverage(path);
        }
      });
    }

    log.debug('Writing coverage reports:', reportTypes);
    reporter.write(remappedCoverageMap, { sourceFinder });

    const userThresholds = coverageConfig.thresholds;

    const thresholds = {
      emitWarning: false,
      global: {
        statements: 0,
        lines: 0,
        branches: 0,
        functions: 0
      },
      each: {
        statements: 0,
        lines: 0,
        branches: 0,
        functions: 0,
        overrides: {}
      }
    };

    if (userThresholds) {
      if (userThresholds.global || userThresholds.each) {
        Object.assign(thresholds.global, userThresholds.global);
        Object.assign(thresholds.each, userThresholds.each);
        if (userThresholds.emitWarning === true) {
          thresholds.emitWarning = true;
        }
      } else {
        Object.assign(thresholds.global, userThresholds);
      }
    }

    let thresholdCheckFailed = false;

    // Adapted from https://github.com/istanbuljs/nyc/blob/98ebdff573be91e1098bb7259776a9082a5c1ce1/index.js#L463-L478
    const globalSummary = remappedCoverageMap.getCoverageSummary();
    const failedGlobalTypes = checkThresholds(thresholds.global, globalSummary);
    failedGlobalTypes.forEach(type => {
      thresholdCheckFailed = true;
      logThresholdMessage(
        thresholds,
        `Coverage for ${type} (${globalSummary[type].pct}%) does not meet global threshold (${thresholds.global[type]}%)`
      );
    });

    remappedCoverageMap.files().forEach(file => {
      const fileThresholds = Object.assign(
        {},
        thresholds.each,
        util.overrideThresholds(
          file,
          thresholds.each.overrides,
          config.basePath
        )
      );
      delete fileThresholds.overrides;
      const fileSummary = remappedCoverageMap.fileCoverageFor(file).toSummary()
        .data;
      const failedFileTypes = checkThresholds(fileThresholds, fileSummary);

      failedFileTypes.forEach(type => {
        thresholdCheckFailed = true;
        if (coverageConfig.fixWebpackSourcePaths) {
          file = util.fixWebpackFilePath(file);
        }

        logThresholdMessage(
          thresholds,
          `Coverage for ${type} (${fileSummary[type].pct}%) in file ${file} does not meet per file threshold (${fileThresholds[type]}%)`
        );
      });
    });

    if (thresholdCheckFailed && results && !thresholds.emitWarning) {
      results.exitCode = 1;
    }
  }

  this.onBrowserComplete = function(browser, result) {
    if (result && result.coverage) {
      browserCoverage.set(browser, result.coverage);
    }
  };

  const baseReporterOnRunComplete = this.onRunComplete;
  this.onRunComplete = function(browsers, results) {
    // eslint-disable-next-line prefer-rest-params
    baseReporterOnRunComplete.apply(this, arguments);

    if (coverageConfig.combineBrowserReports) {
      createReport(browsers, results);
    } else {
      browsers.forEach(browser => {
        createReport(browser, results);
      });
    }
  };
}

CoverageIstanbulReporter.$inject = [
  'baseReporterDecorator',
  'logger',
  'config'
];

module.exports = {
  'reporter:coverage-istanbul': ['type', CoverageIstanbulReporter]
};
