"use strict";

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

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

var _flattenDeep = _interopRequireDefault(require("lodash/flattenDeep"));

var _resolveFrom = _interopRequireDefault(require("resolve-from"));

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

var _getStrictCoatManifest = require("../util/get-strict-coat-manifest");

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

function getTemplates(cwd, context, templateEntry) {
  let template;
  let templateConfig; // extends entries can either be plain strings or
  // tuples in the form of:
  // [templateName, templateConfig]

  if (Array.isArray(templateEntry)) {
    [template, templateConfig] = templateEntry;
  } else {
    template = templateEntry; // Default config is an empty object

    templateConfig = {};
  } // Resolve the directory of the current template to
  // use it as the cwd for child templates.
  //
  // Especially in workspaces node_modules might be deduped
  // or child templates might live in the node_modules folder
  // of the template itself


  const templateDir = _path.default.dirname((0, _resolveFrom.default)(cwd, template)); // Import the current template
  // TODO: See #15
  // Better error message when template can't be imported
  // with a hint to install node_modules


  const templateManifestRawModule = (0, _importFrom.default)(cwd, template); // Check whether the template exported its manifest or manifest function
  // as a default export or directly using module.exports

  let templateManifestRaw;

  if (typeof templateManifestRawModule === "object" && templateManifestRawModule !== null && "__esModule" in templateManifestRawModule && "default" in templateManifestRawModule) {
    templateManifestRaw = templateManifestRawModule.default;
  } else {
    templateManifestRaw = templateManifestRawModule;
  }

  let resolvedTemplate;

  if (typeof templateManifestRaw === "function") {
    resolvedTemplate = (0, _getStrictCoatManifest.getStrictCoatManifest)(templateManifestRaw({
      coatContext: context,
      config: templateConfig
    }));
  } else {
    resolvedTemplate = (0, _getStrictCoatManifest.getStrictCoatManifest)(templateManifestRaw);
  }

  return [...resolvedTemplate.extends.map(childTemplate => getTemplates(templateDir, context, childTemplate)), resolvedTemplate];
}
/**
 * Retrieves and imports all templates that are extended by a coat project.
 *
 * If a single child template is used by multiple templates, it will be not be
 * deduped in order to preserve any logic that depends on the child template being
 * available before the parent template is evaluated.
 *
 * @param context The context of the current coat project
 */


function gatherExtendedTemplates(context) {
  const results = context.coatManifest.extends.map(template => getTemplates(context.cwd, context, template)); // Node.js 10 compatibility
  // Use results.flat(Infinity) once Node 10 is no longer supported

  return (0, _flattenDeep.default)(results);
}