#!node

/*
This ultimately is derived from https://github.com/daton89-topperblues/node-engine-strict
Since this needs to run *before* any dependencies are installed, it must be inlined here.
*/
const path = require("path");
const exec = require("child_process").exec;
const semver = require("./semver");

const getPackageJson = () =>
  new Promise((resolve, reject) => {
    try {
      /* eslint-disable-next-line global-require */
      resolve(require(path.resolve(process.cwd(), "package.json")));
    } catch (error) {
      reject(error);
    }
  });

const getEngines = (data) =>
  new Promise((resolve, reject) => {
    let versions = null;

    if (data.engines) {
      versions = data.engines;
    }

    if (versions) {
      resolve(versions);
    } else {
      reject("Missing or improper 'engines' property in 'package.json'");
    }
  });

const checkNpmVersion = (engines) =>
  new Promise((resolve, reject) => {
    exec("npm -v", (error, stdout, stderr) => {
      if (error) {
        reject(`Unable to find NPM version\n${stderr}`);
      }

      const npmVersion = stdout.trim();
      const engineVersion = engines.npm || ">=0";

      if (semver.satisfies(npmVersion, engineVersion)) {
        resolve();
      } else {
        reject(
          `Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
        );
      }
    });
  });

const checkNodeVersion = (engines) =>
  new Promise((resolve, reject) => {
    const nodeVersion = process.version.substring(1);

    if (semver.satisfies(nodeVersion, engines.node)) {
      resolve(engines);
    } else {
      reject(
        `Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
      );
    }
  });

getPackageJson()
  .then(getEngines)
  .then(checkNodeVersion)
  .then(checkNpmVersion)
  .then(
    () => true,
    (error) => {
      // Specifically disable these as the error message gets lost in the normal unhandled output.
      /* eslint-disable no-console, no-process-exit */
      console.error(error);
      process.exit(1);
    },
  );