'use strict';

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

var _normalizePath;

function _load_normalizePath() {
  return _normalizePath = _interopRequireDefault(require('normalize-path'));
}

var _fileTypesPlugins;

function _load_fileTypesPlugins() {
  return _fileTypesPlugins = _interopRequireDefault(require('../plugins/file-types-plugins'));
}

var _utils;

function _load_utils() {
  return _utils = require('../utils');
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../logger/logger'));
}

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

var LINKS_CONTENT_TEMPLATES = {
  js: "module.exports = require('{filePath}');",
  ts: "export * from '{filePath}';",
  jsx: "export * from '{filePath}';",
  tsx: "export * from '{filePath}';",
  css: "@import '{filePath}.css';",
  scss: "@import '{filePath}.scss';",
  sass: "@import '{filePath}.sass';",
  less: "@import '{filePath}.less';",
  vue: "<script>\nmodule.exports = require('{filePath}.vue');\n</script>"
};

var PACKAGES_LINKS_CONTENT_TEMPLATES = {
  css: "@import '~{filePath}';",
  scss: "@import '~{filePath}';",
  sass: "@import '~{filePath}';",
  less: "@import '~{filePath}';",
  'st.css': ':import { -st-from: "{filePath}";}',
  vue: "<script>\nmodule.exports = require('{filePath}');\n</script>"
};

var fileExtensionsForNpmLinkGenerator = ['js', 'ts', 'jsx', 'tsx'];

function isSupportedExtension(filePath) {
  var ext = (0, (_utils || _load_utils()).getExt)(filePath);
  var supportedExtensions = getSupportedExtensions();
  return supportedExtensions.includes(ext);
}

function getLinkToFileContent(filePath, importSpecifiers) {
  var fileExt = (0, (_utils || _load_utils()).getExt)(filePath);
  if (!filePath.startsWith('.')) {
    filePath = `./${filePath}`; // it must be relative, otherwise, it'll search it in node_modules
  }
  var filePathWithoutExt = (0, (_utils || _load_utils()).getWithoutExt)(filePath);
  var template = getTemplateForFile(fileExt, filePath, importSpecifiers);

  if (!template) return _logWhenNoTemplateWasFound(filePath, fileExt);
  return template.replace(/{filePath}/g, (0, (_normalizePath || _load_normalizePath()).default)(filePathWithoutExt));
}

function getLinkToPackageContent(filePath, bitPackageName) {
  var fileExt = (0, (_utils || _load_utils()).getExt)(filePath);
  var template = getTemplateForPackage(fileExt);
  if (!template) return _logWhenNoTemplateWasFound(filePath, fileExt);
  return template.replace(/{filePath}/g, bitPackageName);
}

function getSupportedExtensions() {
  var extensions = Object.keys(LINKS_CONTENT_TEMPLATES);
  (_fileTypesPlugins || _load_fileTypesPlugins()).default.forEach(function (plugin) {
    extensions.push(plugin.getExtension());
  });
  return extensions;
}

/**
 * Get the template for the generated link file.
 *
 * For ES6 and TypeScript the template is more complicated and we often need to know how originally the variables were
 * imported, whether default (e.g. import foo from './bar') or non-default (e.g. import { foo } from './bar').
 *
 * The importSpecifier.linkFile attribute exists when the main-file doesn't require the variable directly, but uses a
 * link-file to require it indirectly. E.g. src/bar.js: `import foo from './utils;` utils/index.js: `import foo from './foo';`
 */
function getTemplateForFile(fileExt, filePath, importSpecifiers) {
  if (importSpecifiers && importSpecifiers.length) {
    if (fileExt === 'js' || fileExt === 'jsx') {
      // @see e2e/flows/es6-link-files.e2e.js file for cases covered by the following snippet
      return es6TemplateWithImportSpecifiers(importSpecifiers);
    } else if (fileExt === 'ts' || fileExt === 'tsx') {
      return tsTemplateWithImportSpecifiers(importSpecifiers);
    }
  }
  return _getTemplate(fileExt, importSpecifiers);
}

function getTemplateForPackage(fileExt) {
  if (!fileExtensionsForNpmLinkGenerator.includes(fileExt)) {
    return PACKAGES_LINKS_CONTENT_TEMPLATES[fileExt];
  }
  return _getTemplate(fileExt);
}

function _getTemplate(fileExt, importSpecifiers) {
  _addPluginsTemplatesToLinkContentTemplates(importSpecifiers);
  return LINKS_CONTENT_TEMPLATES[fileExt];
}

function _addPluginsTemplatesToLinkContentTemplates(importSpecifiers) {
  (_fileTypesPlugins || _load_fileTypesPlugins()).default.forEach(function (plugin) {
    LINKS_CONTENT_TEMPLATES[plugin.getExtension()] = plugin.getTemplate(importSpecifiers);
  });
}

function _logWhenNoTemplateWasFound(filePath, fileExt) {
  (_logger || _load_logger()).default.debug(`no template was found for ${filePath}, because .${fileExt} extension is not supported`);
  return '';
}

function tsTemplateWithImportSpecifiers(importSpecifiers) {
  return importSpecifiers.map(function (importSpecifier) {
    var importPart = 'import ';
    if (importSpecifier.linkFile && importSpecifier.linkFile.isDefault || !importSpecifier.linkFile && importSpecifier.mainFile.isDefault) {
      importPart += `${importSpecifier.mainFile.name}`;
    } else {
      importPart += `{ ${importSpecifier.mainFile.name} }`;
    }
    importPart += " from '{filePath}';";
    var exportPart = 'export ';
    if (importSpecifier.mainFile.isDefault) {
      exportPart += `default ${importSpecifier.mainFile.name};`;
    } else {
      exportPart += `{ ${importSpecifier.mainFile.name} };`;
    }
    return `${importPart}\n${exportPart}`;
  }).join('\n');
}

function es6TemplateWithImportSpecifiers(importSpecifiers) {
  return importSpecifiers.map(function (importSpecifier) {
    if (!importSpecifier.linkFile) {
      // when no link-file is involved, use the standard non-es6 syntax (a privilege that doesn't exist for TS)
      return LINKS_CONTENT_TEMPLATES.js;
    }
    // for link files we need to know whether the main-file imports the variable as default or non-default
    var exportPart = 'exports';
    if (importSpecifier.mainFile.isDefault) {
      exportPart += '.default';
    } else {
      exportPart += `.${importSpecifier.mainFile.name}`;
    }
    var linkVariable = `_${importSpecifier.linkFile.name}`;
    var linkRequire = `var ${linkVariable} = require('{filePath}');`;
    // when add-module-export babel plugin is used, there is no .default
    // the link-file should support both cases, with and without that plugin
    var pathPart = importSpecifier.linkFile.isDefault ? `${linkVariable} && ${linkVariable}.hasOwnProperty('default') ? ${linkVariable}.default : ${linkVariable}` : `${linkVariable}.${importSpecifier.mainFile.name}`;
    return `${linkRequire}\n${exportPart} = ${pathPart};`;
  }).join('\n');
}