"use strict";

var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };

var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };

var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };

var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };

var DefaultFormatter = _interopRequire(require("./_default"));

var includes = _interopRequire(require("lodash/collection/includes"));

var util = _interopRequireWildcard(require("../../util"));

var t = _interopRequireWildcard(require("../../types"));

var CommonJSFormatter = (function (_DefaultFormatter) {
  function CommonJSFormatter() {
    _classCallCheck(this, CommonJSFormatter);

    if (_DefaultFormatter != null) {
      _DefaultFormatter.apply(this, arguments);
    }
  }

  _inherits(CommonJSFormatter, _DefaultFormatter);

  CommonJSFormatter.prototype.init = function init() {
    var file = this.file;
    var scope = file.scope;

    scope.rename("module");

    if (!this.noInteropRequireImport && this.hasNonDefaultExports) {
      var templateName = "exports-module-declaration";
      if (this.file.isLoose("es6.modules")) templateName += "-loose";
      file.ast.program.body.unshift(util.template(templateName, true));
    }
  };

  CommonJSFormatter.prototype.importSpecifier = function importSpecifier(specifier, node, nodes) {
    var variableName = t.getSpecifierName(specifier);

    var ref = this.getExternalReference(node, nodes);

    // import foo from "foo";
    if (t.isSpecifierDefault(specifier)) {
      if (!includes(this.file.dynamicImportedNoDefault, node)) {
        if (this.noInteropRequireImport || includes(this.file.dynamicImported, node)) {
          ref = t.memberExpression(ref, t.identifier("default"));
        } else {
          ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
        }
      }
      nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)]));
    } else {
      if (specifier.type === "ImportBatchSpecifier") {

        if (!this.noInteropRequireImport) {
          ref = t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]);
        }

        // import * as bar from "foo";
        nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, ref)]));
      } else {
        // import { foo } from "foo";
        nodes.push(t.variableDeclaration("var", [t.variableDeclarator(variableName, t.memberExpression(ref, t.getSpecifierId(specifier)))]));
      }
    }
  };

  CommonJSFormatter.prototype.importDeclaration = function importDeclaration(node, nodes) {
    // import "foo";
    nodes.push(util.template("require", {
      MODULE_NAME: node.source
    }, true));
  };

  CommonJSFormatter.prototype.exportDeclaration = function exportDeclaration(node, nodes) {
    if (this.doDefaultExportInterop(node)) {
      var declar = node.declaration;
      var assign = util.template("exports-default-assign", {
        VALUE: this._pushStatement(declar, nodes)
      }, true);

      if (t.isFunctionDeclaration(declar)) {
        // we can hoist this assignment to the top of the file
        assign._blockHoist = 3;
      }

      nodes.push(assign);
      return;
    }

    DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
  };

  CommonJSFormatter.prototype._getExternalReference = function _getExternalReference(node, nodes) {
    var source = node.source.value;
    var call = t.callExpression(t.identifier("require"), [node.source]);

    if (this.localImportOccurences[source] > 1) {
      var uid = this.scope.generateUidIdentifier(source);
      nodes.push(t.variableDeclaration("var", [t.variableDeclarator(uid, call)]));
      return uid;
    } else {
      return call;
    }
  };

  return CommonJSFormatter;
})(DefaultFormatter);

module.exports = CommonJSFormatter;