(function() {
  var OpalNode, extensions, fs, parser, parserFile, source, sourceFile, vm, __path__;

  sourceFile = "" + __dirname + "/../opal/opal.js";

  parserFile = "" + __dirname + "/../opal/opal-parser.js";

  extensions = ['.opal', '.rb'];

  fs = require('fs');

  __path__ = require('path');

  source = fs.readFileSync(sourceFile).toString();

  parser = fs.readFileSync(parserFile).toString();

  vm = require('vm');

  vm.runInThisContext(source, sourceFile);

  vm.runInThisContext(parser, parserFile);

  OpalNode = (function() {
    function OpalNode() {}

    OpalNode.load_path = [__dirname + '/../opal', __dirname];

    OpalNode.loaded = {};

    OpalNode.backtrace = [];

    OpalNode.node_require = require;

    OpalNode.run = function(ruby, filename) {
      var js;
      js = OpalNode.compile(ruby, {
        file: filename
      });
      return vm.runInThisContext(js, filename);
    };

    OpalNode.compile = function(ruby, options) {
      var compiler, key, keys, required, value, _i, _len, _ref;
      if (options == null) {
        options = void 0;
      }
      if (options && options.klass !== Opal.Hash) {
        keys = (function() {
          var _results;
          _results = [];
          for (key in options) {
            value = options[key];
            _results.push(key);
          }
          return _results;
        })();
        options = Opal.hash2(keys, options);
      }
      compiler = Opal.Opal.Compiler.$new();
      source = compiler.$compile(ruby, options);
      _ref = compiler.$requires();
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        required = _ref[_i];
        OpalNode.require(required);
      }
      return Opal.Opal.$compile(ruby, options);
    };

    OpalNode.resolve = function(filename) {
      var error, filepath, full_path, path, _i, _len, _ref;
      try {
        if (filename.match(/^\./)) {
          filepath = __path__.resolve(process.cwd(), filename);
          return require.resolve(filepath);
        } else {
          _ref = OpalNode.load_path;
          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
            path = _ref[_i];
            full_path = __path__.resolve(path, filename);
            if (fs.existsSync(full_path)) {
              return full_path;
            }
            full_path = full_path.replace(/(\.rb)?$/, '.js');
            if (fs.existsSync(full_path)) {
              return full_path;
            }
          }
          return require.resolve(filename);
        }
      } catch (_error) {
        error = _error;
        if (error.code === 'MODULE_NOT_FOUND' || error.message.indexOf("'" + filename + "'") >= 0) {
          return null;
        } else {
          throw error;
        }
      }
    };

    OpalNode.require = function(filename) {
      var file, full_path, loaded, ruby, ruby_filename, stack;
      ruby_filename = filename.replace(/(\.rb)?$/, '.rb');
      full_path = OpalNode.resolve(ruby_filename);
      if (!full_path) {
        if (filename.match(/\.rb$/)) {
          stack = OpalNode.backtrace;
          file = stack[stack.length - 1] || __filename;
          OpalNode.run("raise LoadError, 'cannot load such file -- " + filename + "'", file);
        } else {
          return require(filename);
        }
      }
      loaded = OpalNode.loaded[filename];
      OpalNode.backtrace.push(filename);
      if (loaded) {
        return false;
      }
      ruby = fs.readFileSync("" + full_path).toString();
      OpalNode.loaded[filename] = true;
      if (full_path.match(/\.js$/)) {
        vm.runInThisContext(ruby, filename);
      } else {
        OpalNode.run(ruby, filename);
      }
      return OpalNode.backtrace.pop();
    };

    return OpalNode;

  })();

  global.OpalNode = OpalNode;

  OpalNode.require(__dirname + '/opal_node');

  OpalNode.require(__dirname + '/file');

  OpalNode.require(__dirname + '/dir');

}).call(this);
