"use strict";

exports.__esModule = true;
exports.rewriteModuleStatementsAndPrepareHeader = rewriteModuleStatementsAndPrepareHeader;
exports.ensureStatementsHoisted = ensureStatementsHoisted;
exports.wrapInterop = wrapInterop;
exports.buildNamespaceInitStatements = buildNamespaceInitStatements;

var _assert = _interopRequireDefault(require("assert"));

var t = _interopRequireWildcard(require("@babel/types"));

var _template = _interopRequireDefault(require("@babel/template"));

var _chunk = _interopRequireDefault(require("lodash/chunk"));

var _helperModuleImports = require("@babel/helper-module-imports");

exports.isModule = _helperModuleImports.isModule;

var _rewriteThis = _interopRequireDefault(require("./rewrite-this"));

var _rewriteLiveReferences = _interopRequireDefault(require("./rewrite-live-references"));

var _normalizeAndLoadMetadata = _interopRequireWildcard(require("./normalize-and-load-metadata"));

exports.hasExports = _normalizeAndLoadMetadata.hasExports;
exports.isSideEffectImport = _normalizeAndLoadMetadata.isSideEffectImport;

var _templateObject = _taggedTemplateLiteralLoose(["var NAME = SOURCE;"], ["var NAME = SOURCE;"]),
    _templateObject2 = _taggedTemplateLiteralLoose(["\n            Object.defineProperty(EXPORTS, \"NAME\", {\n              enumerable: true,\n              get: function() {\n                return NAMESPACE;\n              }\n            });\n          "], ["\n            Object.defineProperty(EXPORTS, \"NAME\", {\n              enumerable: true,\n              get: function() {\n                return NAMESPACE;\n              }\n            });\n          "]),
    _templateObject3 = _taggedTemplateLiteralLoose(["EXPORTS.NAME = NAMESPACE;"], ["EXPORTS.NAME = NAMESPACE;"]),
    _templateObject4 = _taggedTemplateLiteralLoose(["EXPORTS.EXPORT_NAME = NAMESPACE.IMPORT_NAME;"], ["EXPORTS.EXPORT_NAME = NAMESPACE.IMPORT_NAME;"]),
    _templateObject5 = _taggedTemplateLiteralLoose(["\n      Object.defineProperty(EXPORTS, \"EXPORT_NAME\", {\n        enumerable: true,\n        get: function() {\n          return NAMESPACE.IMPORT_NAME;\n        },\n      });\n    "], ["\n      Object.defineProperty(EXPORTS, \"EXPORT_NAME\", {\n        enumerable: true,\n        get: function() {\n          return NAMESPACE.IMPORT_NAME;\n        },\n      });\n    "]),
    _templateObject6 = _taggedTemplateLiteralLoose(["\n        EXPORTS.__esModule = true;\n      "], ["\n        EXPORTS.__esModule = true;\n      "]),
    _templateObject7 = _taggedTemplateLiteralLoose(["\n        Object.defineProperty(EXPORTS, \"__esModule\", {\n          value: true,\n        });\n      "], ["\n        Object.defineProperty(EXPORTS, \"__esModule\", {\n          value: true,\n        });\n      "]),
    _templateObject8 = _taggedTemplateLiteralLoose(["\n        Object.keys(NAMESPACE).forEach(function(key) {\n          if (key === \"default\" || key === \"__esModule\") return;\n          VERIFY_NAME_LIST;\n\n          EXPORTS[key] = NAMESPACE[key];\n        });\n      "], ["\n        Object.keys(NAMESPACE).forEach(function(key) {\n          if (key === \"default\" || key === \"__esModule\") return;\n          VERIFY_NAME_LIST;\n\n          EXPORTS[key] = NAMESPACE[key];\n        });\n      "]),
    _templateObject9 = _taggedTemplateLiteralLoose(["\n        Object.keys(NAMESPACE).forEach(function(key) {\n          if (key === \"default\" || key === \"__esModule\") return;\n          VERIFY_NAME_LIST;\n\n          Object.defineProperty(EXPORTS, key, {\n            enumerable: true,\n            get: function() {\n              return NAMESPACE[key];\n            },\n          });\n        });\n    "], ["\n        Object.keys(NAMESPACE).forEach(function(key) {\n          if (key === \"default\" || key === \"__esModule\") return;\n          VERIFY_NAME_LIST;\n\n          Object.defineProperty(EXPORTS, key, {\n            enumerable: true,\n            get: function() {\n              return NAMESPACE[key];\n            },\n          });\n        });\n    "]),
    _templateObject10 = _taggedTemplateLiteralLoose(["\n            if (Object.prototype.hasOwnProperty.call(EXPORTS_LIST, key)) return;\n          "], ["\n            if (Object.prototype.hasOwnProperty.call(EXPORTS_LIST, key)) return;\n          "]),
    _templateObject11 = _taggedTemplateLiteralLoose(["EXPORTS.NAME = VALUE"], ["EXPORTS.NAME = VALUE"]);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }

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

function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }

function rewriteModuleStatementsAndPrepareHeader(path, _ref) {
  var exportName = _ref.exportName,
      strict = _ref.strict,
      allowTopLevelThis = _ref.allowTopLevelThis,
      strictMode = _ref.strictMode,
      loose = _ref.loose,
      noInterop = _ref.noInterop,
      lazy = _ref.lazy;
  (0, _assert.default)((0, _helperModuleImports.isModule)(path), "Cannot process module statements in a script");
  path.node.sourceType = "script";
  var meta = (0, _normalizeAndLoadMetadata.default)(path, exportName, {
    noInterop: noInterop,
    loose: loose,
    lazy: lazy
  });

  if (!allowTopLevelThis) {
    (0, _rewriteThis.default)(path);
  }

  (0, _rewriteLiveReferences.default)(path, meta);

  if (strictMode !== false) {
    var hasStrict = path.node.directives.some(function (directive) {
      return directive.value.value === "use strict";
    });

    if (!hasStrict) {
      path.unshiftContainer("directives", t.directive(t.directiveLiteral("use strict")));
    }
  }

  var headers = [];

  if ((0, _normalizeAndLoadMetadata.hasExports)(meta) && !strict) {
    headers.push(buildESModuleHeader(meta, loose));
  }

  var nameList = buildExportNameListDeclaration(path, meta);

  if (nameList) {
    meta.exportNameListName = nameList.name;
    headers.push(nameList.statement);
  }

  headers.push.apply(headers, buildExportInitializationStatements(path, meta, loose));
  return {
    meta: meta,
    headers: headers
  };
}

function ensureStatementsHoisted(statements) {
  statements.forEach(function (header) {
    header._blockHoist = 3;
  });
}

function wrapInterop(programPath, expr, type) {
  if (type === "none") {
    return null;
  }

  var helper;

  if (type === "default") {
    helper = "interopRequireDefault";
  } else if (type === "namespace") {
    helper = "interopRequireWildcard";
  } else {
    throw new Error("Unknown interop: " + type);
  }

  return t.callExpression(programPath.hub.file.addHelper(helper), [expr]);
}

function buildNamespaceInitStatements(metadata, sourceMetadata, loose) {
  if (loose === void 0) {
    loose = false;
  }

  var statements = [];
  var srcNamespace = t.identifier(sourceMetadata.name);
  if (sourceMetadata.lazy) srcNamespace = t.callExpression(srcNamespace, []);

  for (var _iterator = sourceMetadata.importsNamespace, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
    var _ref2;

    if (_isArray) {
      if (_i >= _iterator.length) break;
      _ref2 = _iterator[_i++];
    } else {
      _i = _iterator.next();
      if (_i.done) break;
      _ref2 = _i.value;
    }

    var _localName = _ref2;
    if (_localName === sourceMetadata.name) continue;
    statements.push(_template.default.statement(_templateObject)({
      NAME: _localName,
      SOURCE: t.cloneNode(srcNamespace)
    }));
  }

  if (loose) {
    statements.push.apply(statements, buildReexportsFromMeta(metadata, sourceMetadata, loose));
  }

  for (var _iterator2 = sourceMetadata.reexportNamespace, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
    var _ref3;

    if (_isArray2) {
      if (_i2 >= _iterator2.length) break;
      _ref3 = _iterator2[_i2++];
    } else {
      _i2 = _iterator2.next();
      if (_i2.done) break;
      _ref3 = _i2.value;
    }

    var _exportName = _ref3;
    statements.push((sourceMetadata.lazy ? _template.default.statement(_templateObject2) : _template.default.statement(_templateObject3))({
      EXPORTS: metadata.exportName,
      NAME: _exportName,
      NAMESPACE: t.cloneNode(srcNamespace)
    }));
  }

  if (sourceMetadata.reexportAll) {
    var statement = buildNamespaceReexport(metadata, t.cloneNode(srcNamespace), loose);
    statement.loc = sourceMetadata.reexportAll.loc;
    statements.push(statement);
  }

  return statements;
}

var getTemplateForReexport = function getTemplateForReexport(loose) {
  return loose ? _template.default.statement(_templateObject4) : (0, _template.default)(_templateObject5);
};

var buildReexportsFromMeta = function buildReexportsFromMeta(meta, metadata, loose) {
  var namespace = metadata.lazy ? t.callExpression(t.identifier(metadata.name), []) : t.identifier(metadata.name);
  var templateForCurrentMode = getTemplateForReexport(loose);
  return Array.from(metadata.reexports, function (_ref4) {
    var exportName = _ref4[0],
        importName = _ref4[1];
    return templateForCurrentMode({
      EXPORTS: meta.exportName,
      EXPORT_NAME: exportName,
      NAMESPACE: t.cloneNode(namespace),
      IMPORT_NAME: importName
    });
  });
};

function buildESModuleHeader(metadata, enumerable) {
  if (enumerable === void 0) {
    enumerable = false;
  }

  return (enumerable ? _template.default.statement(_templateObject6) : _template.default.statement(_templateObject7))({
    EXPORTS: metadata.exportName
  });
}

function buildNamespaceReexport(metadata, namespace, loose) {
  return (loose ? _template.default.statement(_templateObject8) : _template.default.statement(_templateObject9))({
    NAMESPACE: namespace,
    EXPORTS: metadata.exportName,
    VERIFY_NAME_LIST: metadata.exportNameListName ? (0, _template.default)(_templateObject10)({
      EXPORTS_LIST: metadata.exportNameListName
    }) : null
  });
}

function buildExportNameListDeclaration(programPath, metadata) {
  var exportedVars = Object.create(null);

  for (var _iterator3 = metadata.local.values(), _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
    var _ref5;

    if (_isArray3) {
      if (_i3 >= _iterator3.length) break;
      _ref5 = _iterator3[_i3++];
    } else {
      _i3 = _iterator3.next();
      if (_i3.done) break;
      _ref5 = _i3.value;
    }

    var _data2 = _ref5;

    for (var _iterator5 = _data2.names, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {
      var _ref7;

      if (_isArray5) {
        if (_i5 >= _iterator5.length) break;
        _ref7 = _iterator5[_i5++];
      } else {
        _i5 = _iterator5.next();
        if (_i5.done) break;
        _ref7 = _i5.value;
      }

      var _name2 = _ref7;
      exportedVars[_name2] = true;
    }
  }

  var hasReexport = false;

  for (var _iterator4 = metadata.source.values(), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
    var _ref6;

    if (_isArray4) {
      if (_i4 >= _iterator4.length) break;
      _ref6 = _iterator4[_i4++];
    } else {
      _i4 = _iterator4.next();
      if (_i4.done) break;
      _ref6 = _i4.value;
    }

    var _data3 = _ref6;

    for (var _iterator6 = _data3.reexports.keys(), _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {
      var _ref8;

      if (_isArray6) {
        if (_i6 >= _iterator6.length) break;
        _ref8 = _iterator6[_i6++];
      } else {
        _i6 = _iterator6.next();
        if (_i6.done) break;
        _ref8 = _i6.value;
      }

      var _exportName3 = _ref8;
      exportedVars[_exportName3] = true;
    }

    for (var _iterator7 = _data3.reexportNamespace, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {
      var _ref9;

      if (_isArray7) {
        if (_i7 >= _iterator7.length) break;
        _ref9 = _iterator7[_i7++];
      } else {
        _i7 = _iterator7.next();
        if (_i7.done) break;
        _ref9 = _i7.value;
      }

      var _exportName4 = _ref9;
      exportedVars[_exportName4] = true;
    }

    hasReexport = hasReexport || _data3.reexportAll;
  }

  if (!hasReexport || Object.keys(exportedVars).length === 0) return null;
  var name = programPath.scope.generateUidIdentifier("exportNames");
  delete exportedVars.default;
  return {
    name: name.name,
    statement: t.variableDeclaration("var", [t.variableDeclarator(name, t.valueToNode(exportedVars))])
  };
}

function buildExportInitializationStatements(programPath, metadata, loose) {
  if (loose === void 0) {
    loose = false;
  }

  var initStatements = [];
  var exportNames = [];

  for (var _iterator8 = metadata.local, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {
    var _ref11;

    if (_isArray8) {
      if (_i8 >= _iterator8.length) break;
      _ref11 = _iterator8[_i8++];
    } else {
      _i8 = _iterator8.next();
      if (_i8.done) break;
      _ref11 = _i8.value;
    }

    var _ref13 = _ref11;
    var _localName2 = _ref13[0];
    var _data5 = _ref13[1];

    if (_data5.kind === "import") {} else if (_data5.kind === "hoisted") {
      initStatements.push(buildInitStatement(metadata, _data5.names, t.identifier(_localName2)));
    } else {
      exportNames.push.apply(exportNames, _data5.names);
    }
  }

  for (var _iterator9 = metadata.source.values(), _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {
    var _ref12;

    if (_isArray9) {
      if (_i9 >= _iterator9.length) break;
      _ref12 = _iterator9[_i9++];
    } else {
      _i9 = _iterator9.next();
      if (_i9.done) break;
      _ref12 = _i9.value;
    }

    var _data6 = _ref12;

    if (!loose) {
      initStatements.push.apply(initStatements, buildReexportsFromMeta(metadata, _data6, loose));
    }

    for (var _iterator10 = _data6.reexportNamespace, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {
      var _ref14;

      if (_isArray10) {
        if (_i10 >= _iterator10.length) break;
        _ref14 = _iterator10[_i10++];
      } else {
        _i10 = _iterator10.next();
        if (_i10.done) break;
        _ref14 = _i10.value;
      }

      var _exportName5 = _ref14;
      exportNames.push(_exportName5);
    }
  }

  initStatements.push.apply(initStatements, (0, _chunk.default)(exportNames, 100).map(function (members) {
    return buildInitStatement(metadata, members, programPath.scope.buildUndefinedNode());
  }));
  return initStatements;
}

function buildInitStatement(metadata, exportNames, initExpr) {
  return t.expressionStatement(exportNames.reduce(function (acc, exportName) {
    return _template.default.expression(_templateObject11)({
      EXPORTS: metadata.exportName,
      NAME: exportName,
      VALUE: acc
    });
  }, initExpr));
}