       return COLORS_16m;
      default:
        return COLORS_2;
    }
  }

  if (env.NODE_DISABLE_COLORS !== undefined ||
      // See https://no-color.org/
      env.NO_COLOR !== undefined ||
      // The "dumb" special terminal, as defined by terminfo, doesn't support
      // ANSI color control codes.
      // See https://invisible-island.net/ncurses/terminfo.ti.html#toc-_Specials
      env.TERM === 'dumb') {
    return COLORS_2;
  }

  if (process.platform === 'win32') {
    // Lazy load for startup performance.
    if (OSRelease === undefined) {
      const { release } = require('os');
      OSRelease = StringPrototypeSplit(release(), '.');
    }
    // Windows 10 build 10586 is the first Windows release that supports 256
    // colors. Windows 10 build 14931 is the first release that supports
    // 16m/TrueColor.
    if (+OSRelease[0] >= 10) {
      const build = +OSRelease[2];
      if (build >= 14931)
        return COLORS_16m;
      if (build >= 10586)
        return COLORS_256;
    }

    return COLORS_16;
  }

  if (env.TMUX) {
    return COLORS_256;
  }

  if (env.CI) {
    if ([
      'APPVEYOR',
      'BUILDKITE',
      'CIRCLECI',
      'DRONE',
      'GITHUB_ACTIONS',
      'GITLAB_CI',
      'TRAVIS',
    ].some((sign) => sign in env) || env.CI_NAME === 'codeship') {
      return COLORS_256;
    }
    return COLORS_2;
  }

  if ('TEAMCITY_VERSION' in env) {
    return RegExpPrototypeExec(/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/, env.TEAMCITY_VERSION) !== null ?
      COLORS_16 : COLORS_2;
  }

  switch (env.TERM_PROGRAM) {
    case 'iTerm.app':
      if (!env.TERM_PROGRAM_VERSION ||
        RegExpPrototypeExec(/^[0-2]\./, env.TERM_PROGRAM_VERSION) !== null
      ) {
        return COLORS_256;
      }
      return COLORS_16m;
    case 'HyperTerm':
    case 'MacTerm':
      return COLORS_16m;
    case 'Apple_Terminal':
      return COLORS_256;
  }

  if (env.COLORTERM === 'truecolor' || env.COLORTERM === '24bit') {
    return COLORS_16m;
  }

  if (env.TERM) {
    if (RegExpPrototypeExec(/^xterm-256/, env.TERM) !== null) {
      return COLORS_256;
    }

    const termEnv = StringPrototypeToLowerCase(env.TERM);

    if (TERM_ENVS[termEnv]) {
      return TERM_ENVS[termEnv];
    }
    if (ArrayPrototypeSome(TERM_ENVS_REG_EXP,
                           (term) => RegExpPrototypeExec(term, termEnv) !== null)) {
      return COLORS_16;
    }
  }
  // Move 16 color COLORTERM below 16m and 256
  if (env.COLORTERM) {
    return COLORS_16;
  }
  return COLORS_2;
}

function hasColors(count, env) {
  if (env === undefined &&
      (count === undefined || (typeof count === 'object' && count !== null))) {
    env = count;
    count = 16;
  } else {
    validateInteger(count, 'count', 2);
  }

  return count <= 2 ** getColorDepth(env);
}

module.exports = {
  getColorDepth,
  hasColors,
};
