// Generated by CoffeeScript 1.7.0
(function() {
  var Adapter, File, W, fs, path, requireEngine, resolve, resolvePath, _,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  File = require('fobject');

  W = require('when');

  _ = require('lodash');

  resolve = require('resolve');

  path = require('path');

  fs = require('fs');

  Adapter = (function() {

    /**
     * The names of the npm modules that are supported to be used as engines by
       the adapter. Defaults to the name of the adapter.
     * @type {String[]}
     */
    Adapter.prototype.supportedEngines = void 0;


    /**
     * The name of the engine in-use. Generally this is the name of the package on
       npm.
     * @type {String}
     */

    Adapter.prototype.engineName = '';


    /**
     * The actual engine, no adapter wrapper. Defaults to the engine that we
       recommend for compiling that particular language (if it is installed).
       Otherwise, whatever engine we support that is installed.
     */

    Adapter.prototype.engine = void 0;


    /**
     * Array of all file extensions the compiler should match
     * @type {String[]}
     */

    Adapter.prototype.extensions = void 0;


    /**
     * Expected output extension
     * @type {String}
     */

    Adapter.prototype.output = '';


    /**
     * @param {String} [engine=Adapter.supportedEngines[0]] If you need to use a
       particular engine to compile/render with, then specify it here. Otherwise
       we use whatever engine you have installed.
     */

    function Adapter(engineName, customPath) {
      var _i, _len, _ref, _ref1;
      this.engineName = engineName;
      if (!this.supportedEngines || this.supportedEngines.length === 0) {
        this.supportedEngines = [this.name];
      }
      if (this.engineName != null) {
        if (_ref = this.engineName, __indexOf.call(this.supportedEngines, _ref) < 0) {
          throw new Error("engine '" + this.engineName + "' not supported");
        }
        this.engine = requireEngine(this.engineName, customPath);
      } else {
        _ref1 = this.supportedEngines;
        for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
          this.engineName = _ref1[_i];
          try {
            this.engine = requireEngine(this.engineName, customPath);
          } catch (_error) {
            continue;
          }
          return;
        }
        throw new Error("'tried to require: " + this.supportedEngines + "'.\nNone found. Make sure one has been installed!");
      }
    }


    /**
     * Render a string to a compiled string
     * @param {String} str
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.render = function(str, opts) {
      if (opts == null) {
        opts = {};
      }
      if (!this._render) {
        return W.reject(new Error('render not supported'));
      }
      return this._render(str, opts);
    };


    /**
     * Render a file to a compiled string
     * @param {String} file The path to the file
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.renderFile = function(file, opts) {
      if (opts == null) {
        opts = {};
      }
      opts = _.clone(opts, true);
      return (new File(file)).read({
        encoding: 'utf8'
      }).then(_.partialRight(this.render, _.extend(opts, {
        filename: file
      })).bind(this));
    };


    /**
     * Compile a string to a function
     * @param {String} str
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.compile = function(str, opts) {
      if (opts == null) {
        opts = {};
      }
      if (!this._compile) {
        return W.reject(new Error('compile not supported'));
      }
      return this._compile(str, opts);
    };


    /**
     * Compile a file to a function
     * @param {String} file The path to the file
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.compileFile = function(file, opts) {
      if (opts == null) {
        opts = {};
      }
      return (new File(file)).read({
        encoding: 'utf8'
      }).then(_.partialRight(this.compile, _.extend(opts, {
        filename: file
      })).bind(this));
    };


    /**
     * Compile a string to a client-side-ready function
     * @param {String} str
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.compileClient = function(str, opts) {
      if (opts == null) {
        opts = {};
      }
      if (!this._compileClient) {
        return W.reject(new Error('client-side compile not supported'));
      }
      return this._compileClient(str, opts);
    };


    /**
     * Compile a file to a client-side-ready function
     * @param {String} file The path to the file
     * @param {Object} [opts = {}]
     * @return {Promise}
     */

    Adapter.prototype.compileFileClient = function(file, opts) {
      if (opts == null) {
        opts = {};
      }
      return (new File(file)).read({
        encoding: 'utf8'
      }).then(_.partialRight(this.compileClient, _.extend(opts, {
        filename: file
      })).bind(this));
    };


    /**
     * Some adapters that compile for client also need helpers, this method
       returns a string of minfied JavaScript with all of them
     * @return {Promise} A promise for the client-side helpers.
     */

    Adapter.prototype.clientHelpers = void 0;

    return Adapter;

  })();

  requireEngine = function(engineName, customPath) {
    var engine, err;
    if (customPath != null) {
      engine = require(resolve.sync(path.basename(customPath), {
        basedir: customPath
      }));
      engine.__accord_path = customPath;
    } else {
      try {
        engine = require(engineName);
        engine.__accord_path = resolvePath(engineName);
      } catch (_error) {
        err = _error;
        throw new Error("'" + engineName + "' not found. make sure it has been installed!");
      }
    }
    return engine;
  };


  /**
   * Get the path to the root folder of a node module, given its name.
   * @param  {String} name The name of the node module you want the path to.
   * @return {String} The root folder of node module `name`.
   * @private
   */

  resolvePath = function(name) {
    var filepath;
    filepath = require.resolve(name);
    while (true) {
      if (path === '/') {
        throw new Error("cannot resolve root of node module " + name);
      }
      filepath = path.dirname(filepath);
      if (fs.existsSync(path.join(filepath, 'package.json'))) {
        return filepath;
      }
    }
  };

  module.exports = Adapter;

}).call(this);
