'use strict';
const path = require('path');
const compareVersions = require('compare-versions');
const chalk = require('chalk');

/**
 * @typedef {import('../types').Identifier} Identifier
 * @typedef {import('../types').SimpleSupportStatement} SimpleSupportStatement
 * @typedef {import('../types').SupportBlock} SupportBlock
 * @typedef {import('../types').VersionValue} VersionValue
 */
const browsers = require('..').browsers;

/** @type {Object<string, string[]>} */
const validBrowserVersions = {};
for (const browser of Object.keys(browsers)) {
  validBrowserVersions[browser] = Object.keys(browsers[browser].releases);
}

/**
 * @param {string} browserIdentifier
 * @param {VersionValue} version
 */
function isValidVersion(browserIdentifier, version) {
  if (typeof version === 'string') {
    return validBrowserVersions[browserIdentifier].includes(version);
  } else {
    return true;
  }
}

/**
 * @param {string} dataFilename
 */
function testVersions(dataFilename) {
  const data = require(dataFilename);
  let hasErrors = false;

  /**
   * @param {SupportBlock} supportData
   */
  function checkVersions(supportData) {
    const browsersToCheck = Object.keys(supportData);
    for (const browser of browsersToCheck) {
      if (validBrowserVersions[browser]) {
        /** @type {SimpleSupportStatement[]} */
        const supportStatements = [];
        if (Array.isArray(supportData[browser])) {
          Array.prototype.push.apply(supportStatements, supportData[browser]);
        } else {
          supportStatements.push(supportData[browser]);
        }

        const validBrowserVersionsString =
          'true, false, null' +
          (validBrowserVersions[browser].length > 0
            ? ', ' + validBrowserVersions[browser].join(', ')
            : '');
        const validBrowserVersionsTruthy =
          validBrowserVersions[browser].length > 0
            ? 'true, ' + validBrowserVersions[browser].join(', ')
            : 'true';

        for (const statement of supportStatements) {
          if (!isValidVersion(browser, statement.version_added)) {
            console.error(chalk.red(
              `  version_added: "${
                statement.version_added
              }" is not a valid version number for ${browser}`,
            ));
            console.error(chalk.red(`  Valid ${browser} versions are: ${validBrowserVersionsString}`));
            hasErrors = true;
          }
          if (!isValidVersion(browser, statement.version_removed)) {
            console.error(chalk.red(
              `  version_removed: "${
                statement.version_removed
              }" is not a valid version number for ${browser}`,
            ));
            console.error(chalk.red(`  Valid ${browser} versions are: ${validBrowserVersionsString}`));
            hasErrors = true;
          }
          if ('version_removed' in statement && 'version_added' in statement) {
            if (
              typeof statement.version_added !== 'string' &&
              statement.version_added !== true
            ) {
              console.error(chalk.red(
                `  version_added: "${
                  statement.version_added
                }" is not a valid version number when version_removed is present`,
              ));
              console.error(chalk.red(`  Valid ${browser} versions are: ${validBrowserVersionsTruthy}`));
              hasErrors = true;
            } else if (
              typeof statement.version_added === 'string' &&
              typeof statement.version_removed === 'string' &&
              compareVersions(statement.version_added, statement.version_removed) >= 0
            ) {
              console.error(chalk.red(
                `  version_removed: "${
                  statement.version_removed
                }" must be greater than version_added: "${
                  statement.version_added
                }"`,
              ));
              hasErrors = true;
            }
          }
        }
      }
    }
  }

  /**
   * @param {Identifier} data
   */
  function findSupport(data) {
    for (const prop in data) {
      if (prop === '__compat' && data[prop].support) {
        checkVersions(data[prop].support);
      }
      const sub = data[prop];
      if (typeof sub === 'object') {
        findSupport(sub);
      }
    }
  }
  findSupport(data);

  if (hasErrors) {
    console.error(chalk.red(`  File : ${path.relative(process.cwd(), dataFilename)}`));
    console.error(chalk.red('  Browser version error(s)'));
    return true;
  } else {
    return false;
  }
}

module.exports = testVersions;

@@ -1618,20 +1618,10 @@
 ng =
-%0A          '
+ %60
 true
@@ -1637,85 +1637,12 @@
 null
-' +%0A          (validBrowserVersions%5Bbrowser%5D.length %3E 0%0A            ? ', ' + 
+, $%7B
 vali
@@ -1681,26 +1681,10 @@
 , ')
-%0A            : '')
+%7D%60
 ;%0A  
@@ -1727,85 +1727,18 @@
 hy =
-%0A          validBrowserVersions%5Bbrowser%5D.length %3E 0%0A            ? '
+ %60
 true, 
-' + 
+$%7B
 vali
@@ -1777,29 +1777,10 @@
 , ')
-%0A            : 'true'
+%7D%60
 ;%0A%0A 

remove redundant array length test and switch to string literals (#4082)