exports.fetch = function(load) {
  if (this.builder)
    return '';

  if (load.address.indexOf('*') == -1)
    return 'module.exports = "' + load.address + '";';
  else
    return '';
};

exports.translate = function(load, traceOpts) {
  function makeRootRelative(fileUrl) {
    if (traceOpts.assetRoot && fileUrl.indexOf(traceOpts.assetRoot) === 0) {
      return fileUrl.replace(traceOpts.assetRoot, '/');
    }
    return fileUrl;
  }

  if (!this.builder || !traceOpts.production) {
    load.metadata.build = false;
    return load.source;
  }

  // load.metadata.timestamp = -1;

  if (load.address.indexOf('*') == -1)
    return 'module.exports = "' + makeRootRelative(load.address) + '".toString("url")';

  var isWin = process.platform.match(/^win/);
  function fromFileURL(url) {
    return url.substr(7 + !!isWin).replace(/\//g, isWin ? '\\' : '/');
  }
  function toFileURL(path) {
    return 'file://' + (isWin ? '/' : '') + path.replace(/\\/g, '/');
  }

  // assume normalized is a URL that can glob the filesystem
  return new Promise(function(resolve, reject) {
    var pathPattern = fromFileURL(load.address);
    var queryString = '';
    pathPattern = pathPattern.replace(/\?.*$/, function ($0) {
        queryString = $0;
        return '';
    });

    System._nodeRequire('glob')(pathPattern, {
      nobrace: true,
      noext: true,
      nodir: true
    }, function(err, files) {
      if (err)
        reject(err);

      var regexPattern = new RegExp(pathPattern
      // regex escape
      .replace(/[\\^$+?.()|[\]{}]/g, '\\$&')
      // glob captures for * and **
      .replace(/\*\*\/\*/g, '([\\s\\S]+)')
      .replace(/\*\*/g, '([\\s\\S]+)')
      .replace(/\*/g, '([^\\/]+)'));

      var obj = {};

      files.forEach(function(file) {

        var segments = file.match(regexPattern).slice(1);

        var curObj = obj;

        segments.forEach(function(segment, index) {
          if (index == segments.length - 1)
            curObj[segment] = makeRootRelative(toFileURL(file) + queryString);
          else
            curObj = curObj[segment] = curObj[segment] || {};
        });
      });

      // custom serializer into object form with .toString('url') annotations
      // that are picked up by AssetGraph
      var objStr = '';
      function serialize(obj, ws) {
        var objStr = '{';
        ws = ws || '\n';
        ws += '\t';
        var keys = Object.keys(obj);
        keys.forEach(function(key, index) {
          objStr += ws + '"' + key + '": ';
          if (typeof obj[key] == 'string')
            objStr += '"' + obj[key] + '".toString("url")';
          else
            objStr += serialize(obj[key]);
          if (index != keys.length - 1)
            objStr += ',';
        });
        return objStr + '}';
      }

      resolve('var obj = ' + serialize(obj) + '\n' +
        'module.exports = function() {\n' +
        '  var output = obj;\n' +
        '  for (var i = 0; i < arguments.length; i++) {\n' +
        '    if (typeof obj[arguments[i]] !== \'object\' && i !== arguments.length - 1)\n' +
        '      throw new TypeError(\'Unable to read argument "\' + arguments[i] + \'" from glob in \' + module.id);\n' +
        '    output = output[arguments[i]];\n' +
        '  }\n' +
        '  return output;\n' +
        '};'
      );
    });
  });
};

exports.instantiate = function(load) {
  if (load.address.indexOf('*') == -1)
    return load.address;

  return function() {
    var args = arguments;
    var i = 0;
    return load.address.replace(/\*\*\/\*|\*\*|\*/g, function(star) {
      return args[i++];
    });
  };
};
