var utils = require('./utils');

function Program(main) {
  this.main = main;
}

Program.prototype.toAMD = function(opts) {
  opts = opts || {}
  
  var js = ''
    , transitive = opts.transitive || false
    , newline = opts.newline = '\n';
    
  // Module IDs must be burned when transporting multiple modules in a single
  // script.
  if (transitive) { opts.burnID = true; }
  
  // Traverse the module tree, constructing AMD-compatible JavaScript.  If
  // the `transitive` option is disabled, the tree will consist of just a
  // single module.
  traverse(this.main, function(mod) {
    if (!mod.filename) { return; }
    
    var mopts = {};
    utils.merge(mopts, opts);
    if (mod.id == opts.main) {
      // The main module of a program is wrapped in a `require` call, so that
      // its execution is triggered upon load.
      utils.merge(mopts, { define: 'require' });
    }
    if (opts.transitive && !mod.parent) {
      // TODO: Move this toAMD(), `node` case.
    
      // If the module has no parent, burn the ID specified by the client in
      // order to keep state consistent between the client and server.
      //
      // In practice, the only time these would differ is when requesting a
      // top-level Node module in which the main JavaScript file resolves to
      // an internal file inside a lib directory (referenced through the
      // `main` property of package.json).
      utils.merge(mopts, { moduleID: mod.id });
    }
    
    js += mod.toAMD(mopts) + newline;
  });
  
  return js;
}

module.exports = Program;


function traverse(m, fn) {
  m.children.forEach(function(child) {
    traverse(child, fn);
  });
  fn(m);
}

@@ -145,16 +145,34 @@
   %0A  var
+ self = this%0A    ,
  js = ''
@@ -172,16 +172,16 @@
 js = ''%0A
-
     , tr
@@ -472,17 +472,17 @@
   If
+ the
 %0A  //
- the
  %60tr
@@ -546,20 +546,20 @@
 st a
-%0A  //
  single
+%0A  //
  mod
@@ -910,21 +910,16 @@
     if (
-opts.
 transiti
@@ -928,160 +928,148 @@
  && 
-!mod.parent) %7B%0A      // TODO: Move this toAMD(), %60node%60 case.%0A    %0A      // If the module has no parent, burn the ID specified by the client in%0A      //
+self.main == mod) %7B%0A      // For top-level modules, the client will request the module with a notion%0A      // of what its identifier is.  In
  ord
@@ -1103,16 +1103,25 @@
  between
+%0A      //
  the cli
@@ -1138,134 +1138,431 @@
 rver
-.%0A      //%0A      // In practice, the only time these would differ is when requesting a%0A      // top-level Node module in which
+, that same identifier needs to be burned when%0A      // transporting the module.  By default, the module's absolute ID is%0A      // burned as that conforms to the majority of AMD resolution cases.%0A      // However, the following cases adjust for situations in which that%0A      // assumption does not hold.%0A      %0A      switch (mod.resolve.__algo) %7B%0A        case 'node':%0A          // In practice, Node identifiers differ when
  the
@@ -1582,16 +1582,29 @@
 ipt file
+%0A          //
  resolve
@@ -1607,25 +1607,16 @@
 olves to
-%0A      //
  an inte
@@ -1659,16 +1659,29 @@
 ferenced
+%0A          //
  through
@@ -1684,25 +1684,16 @@
 ough the
-%0A      //
  %60main%60 
@@ -1718,17 +1718,84 @@
 e.json).
-%0A
+  For example:%0A          //   junction -%3E junction/lib/index.js%0A    
       ut
@@ -1830,24 +1830,49 @@
  mod.id %7D);%0A
+          break;%0A      %7D%0A
     %7D%0A    %0A 

Clean up Node case for burning top-level module id.