"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getTemplateInfo = getTemplateInfo;

var _fs = require("fs");

var _path = _interopRequireDefault(require("path"));

var _tmp = _interopRequireDefault(require("tmp"));

var _importFrom = _interopRequireDefault(require("import-from"));

var _execa = _interopRequireDefault(require("execa"));

var _chalk = _interopRequireDefault(require("chalk"));

var _difference = _interopRequireDefault(require("lodash/difference"));

var _constants = require("../constants");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Retrieves the package.json of a freshly installed
 * template in a project folder by comparing the package.json
 * files before and after the template has been installed.
 *
 * If the template has already been installed before in the project,
 * it will be installed again in to a temporary project to be able
 * to correctly retrieve the template name and manifest information.
 *
 * @param cwd The directory of the newly created coat project
 * @param previousPackageJson The previous package.json content, to compare it
 *   with the updated version after npm install has been run
 * @param template The template string that was used in `coat create`.
 *   Will be used to install the template in a temporary directory if necessary
 * @param installSpinner The loading spinner that is displayed during
 *   `coat create`. It will be updated in case the template has to be
 *   installed in a temporary directory
 */
async function getTemplateInfo(cwd, previousPackageJson, template, installSpinner) {
  var _previousPackageJson$;

  // Retrieve the current package.json file for later comparison
  const currentPackageJsonRaw = await _fs.promises.readFile(_path.default.join(cwd, _constants.PACKAGE_JSON_FILENAME), "utf-8");
  const currentPackageJson = JSON.parse(currentPackageJsonRaw); // Get the name of the new devDependency that has been installed
  // to get the correct template name by comparing current devDepndencies
  // to the previous devDependencies.
  // Since only a single dependency - the template itself - was installed,
  // it should be the only entry in the difference array

  const [templatePackageName] = (0, _difference.default)(Object.keys(currentPackageJson.devDependencies), Object.keys((_previousPackageJson$ = previousPackageJson.devDependencies) !== null && _previousPackageJson$ !== void 0 ? _previousPackageJson$ : {}));

  if (templatePackageName) {
    // Import the package.json file of the template package
    return (0, _importFrom.default)(cwd, `${templatePackageName}/${_constants.PACKAGE_JSON_FILENAME}`);
  } // If templatePackageName is undefined, it means that the
  // template already existed in the devDependencies of the
  // project.
  // Install the template again in a temporary directory to
  // retrieve the difference.
  // eslint-disable-next-line no-param-reassign


  installSpinner.text = `${_chalk.default.cyan("coat")} was not able to determine the template name and peerDependencies directly by installing the template and has to do an extra round to retrieve information about the installed template.\nThis is likely due to the template already being installed in the project directory before. This might take a couple of minutes.\n`; //
  // Create a temporary directory

  const tmpDir = _tmp.default.dirSync({
    unsafeCleanup: true
  }); // Write an empty package.json file into the temporary directory


  await _fs.promises.writeFile(_path.default.join(tmpDir.name, _constants.PACKAGE_JSON_FILENAME), JSON.stringify({
    name: "tmp-project-for-template-info",
    version: "1.0.0"
  })); // Install the template into the temporary directory

  await (0, _execa.default)("npm", ["install", "--save-exact", "--save-dev", template], {
    cwd: tmpDir.name
  }); // Retrieve the updated temporary package.json file for comparison

  const tmpCurrentPackageJsonRaw = await _fs.promises.readFile(_path.default.join(tmpDir.name, _constants.PACKAGE_JSON_FILENAME), "utf-8");
  const tmpCurrentPackageJson = JSON.parse(tmpCurrentPackageJsonRaw); // Get the name of the new devDependency that has been installed
  // to get the correct template name by comparing current devDepndencies
  // to the previous devDependencies.
  // Since only a single dependency - the template itself - was installed,
  // it should be the only entry in the difference array

  const [tmpTemplatePackageName] = (0, _difference.default)(Object.keys(tmpCurrentPackageJson.devDependencies), Object.keys({})); // Import the package.json file of the template package in the temporary
  // project directory

  const templateInfo = (0, _importFrom.default)(tmpDir.name, `${tmpTemplatePackageName}/${_constants.PACKAGE_JSON_FILENAME}`); // Remove temporary directory

  tmpDir.removeCallback();
  return templateInfo;
}