#!/usr/bin/env node
// -*- mode: js -*-
"use strict";

var getAllVisitors = require('../vendor/fbtransform/visitors').getAllVisitors;
var transform = require('jstransform').transform;
var propagate = require("../vendor/constants").propagate;

require("commoner").version(
  require("../package.json").version
).resolve(function(id) {
  var context = this;

  // Note that the result of context.getProvidedP() is cached for the
  // duration of the build, so it is both consistent and cheap to
  // evaluate multiple times.
  return context.getProvidedP().then(function(idToPath) {
    // If a module declares its own identifier using @providesModule
    // then that identifier will be a key in the idToPath object.
    if (idToPath.hasOwnProperty(id)) {
      return context.readFileP(idToPath[id]);
    }

    // Otherwise assume the identifier maps directly to a path in the
    // filesystem.
    return context.readModuleP(id);
  });

}).process(function(id, source) {
  var context = this;
  var constants = context.config.constants || {};

  // This is where JSX, ES6, etc. desugaring happens.
  source = transform(getAllVisitors(), source).code;

  // Constant propagation means removing any obviously dead code after
  // replacing constant expressions with literal (boolean) values.
  source = propagate(constants, source);

  if (context.config.mocking) {
    // Make sure there is exactly one newline at the end of the module.
    source = source.replace(/\s+$/m, "\n");

    return context.getProvidedP().then(function(idToPath) {
      if (id !== "mock-modules" &&
          id !== "mocks" &&
          id !== "test/all" &&
          idToPath.hasOwnProperty("mock-modules")) {
        return source + '\nrequire("mock-modules").register(' +
          JSON.stringify(id) + ', module);\n';
      }

      return source;
    });
  }

  return source;
});
