// Generated by CoffeeScript 1.10.0
var ReqlAuthError, ReqlAvailabilityError, ReqlCompileError, ReqlDriverCompileError, ReqlDriverError, ReqlError, ReqlInternalError, ReqlNonExistenceError, ReqlOpFailedError, ReqlOpIndeterminateError, ReqlPermissionError, ReqlQueryLogicError, ReqlQueryPrinter, ReqlResourceLimitError, ReqlRuntimeError, ReqlServerCompileError, ReqlTimeoutError, ReqlUserError,
  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  hasProp = {}.hasOwnProperty;

ReqlError = (function(superClass) {
  extend(ReqlError, superClass);

  function ReqlError(msg, term, frames) {
    this.name = this.constructor.name;
    this.msg = msg;
    this.frames = frames != null ? frames.slice(0) : void 0;
    if (term != null) {
      if (msg[msg.length - 1] === '.') {
        this.message = (msg.slice(0, msg.length - 1)) + " in:\n" + (ReqlQueryPrinter.prototype.printQuery(term)) + "\n" + (ReqlQueryPrinter.prototype.printCarrots(term, frames));
      } else {
        this.message = msg + " in:\n" + (ReqlQueryPrinter.prototype.printQuery(term)) + "\n" + (ReqlQueryPrinter.prototype.printCarrots(term, frames));
      }
    } else {
      this.message = "" + msg;
    }
    if (Error.captureStackTrace != null) {
      Error.captureStackTrace(this, this);
    }
  }

  return ReqlError;

})(Error);

ReqlCompileError = (function(superClass) {
  extend(ReqlCompileError, superClass);

  function ReqlCompileError() {
    return ReqlCompileError.__super__.constructor.apply(this, arguments);
  }

  return ReqlCompileError;

})(ReqlError);

ReqlDriverCompileError = (function(superClass) {
  extend(ReqlDriverCompileError, superClass);

  function ReqlDriverCompileError() {
    return ReqlDriverCompileError.__super__.constructor.apply(this, arguments);
  }

  return ReqlDriverCompileError;

})(ReqlCompileError);

ReqlServerCompileError = (function(superClass) {
  extend(ReqlServerCompileError, superClass);

  function ReqlServerCompileError() {
    return ReqlServerCompileError.__super__.constructor.apply(this, arguments);
  }

  return ReqlServerCompileError;

})(ReqlCompileError);

ReqlDriverError = (function(superClass) {
  extend(ReqlDriverError, superClass);

  function ReqlDriverError() {
    return ReqlDriverError.__super__.constructor.apply(this, arguments);
  }

  return ReqlDriverError;

})(ReqlError);

ReqlAuthError = (function(superClass) {
  extend(ReqlAuthError, superClass);

  function ReqlAuthError() {
    return ReqlAuthError.__super__.constructor.apply(this, arguments);
  }

  return ReqlAuthError;

})(ReqlDriverError);

ReqlRuntimeError = (function(superClass) {
  extend(ReqlRuntimeError, superClass);

  function ReqlRuntimeError() {
    return ReqlRuntimeError.__super__.constructor.apply(this, arguments);
  }

  return ReqlRuntimeError;

})(ReqlError);

ReqlQueryLogicError = (function(superClass) {
  extend(ReqlQueryLogicError, superClass);

  function ReqlQueryLogicError() {
    return ReqlQueryLogicError.__super__.constructor.apply(this, arguments);
  }

  return ReqlQueryLogicError;

})(ReqlRuntimeError);

ReqlNonExistenceError = (function(superClass) {
  extend(ReqlNonExistenceError, superClass);

  function ReqlNonExistenceError() {
    return ReqlNonExistenceError.__super__.constructor.apply(this, arguments);
  }

  return ReqlNonExistenceError;

})(ReqlQueryLogicError);

ReqlResourceLimitError = (function(superClass) {
  extend(ReqlResourceLimitError, superClass);

  function ReqlResourceLimitError() {
    return ReqlResourceLimitError.__super__.constructor.apply(this, arguments);
  }

  return ReqlResourceLimitError;

})(ReqlRuntimeError);

ReqlUserError = (function(superClass) {
  extend(ReqlUserError, superClass);

  function ReqlUserError() {
    return ReqlUserError.__super__.constructor.apply(this, arguments);
  }

  return ReqlUserError;

})(ReqlRuntimeError);

ReqlInternalError = (function(superClass) {
  extend(ReqlInternalError, superClass);

  function ReqlInternalError() {
    return ReqlInternalError.__super__.constructor.apply(this, arguments);
  }

  return ReqlInternalError;

})(ReqlRuntimeError);

ReqlTimeoutError = (function(superClass) {
  extend(ReqlTimeoutError, superClass);

  function ReqlTimeoutError() {
    return ReqlTimeoutError.__super__.constructor.apply(this, arguments);
  }

  return ReqlTimeoutError;

})(ReqlError);

ReqlAvailabilityError = (function(superClass) {
  extend(ReqlAvailabilityError, superClass);

  function ReqlAvailabilityError() {
    return ReqlAvailabilityError.__super__.constructor.apply(this, arguments);
  }

  return ReqlAvailabilityError;

})(ReqlRuntimeError);

ReqlOpFailedError = (function(superClass) {
  extend(ReqlOpFailedError, superClass);

  function ReqlOpFailedError() {
    return ReqlOpFailedError.__super__.constructor.apply(this, arguments);
  }

  return ReqlOpFailedError;

})(ReqlAvailabilityError);

ReqlOpIndeterminateError = (function(superClass) {
  extend(ReqlOpIndeterminateError, superClass);

  function ReqlOpIndeterminateError() {
    return ReqlOpIndeterminateError.__super__.constructor.apply(this, arguments);
  }

  return ReqlOpIndeterminateError;

})(ReqlAvailabilityError);

ReqlPermissionError = (function(superClass) {
  extend(ReqlPermissionError, superClass);

  function ReqlPermissionError() {
    return ReqlPermissionError.__super__.constructor.apply(this, arguments);
  }

  return ReqlPermissionError;

})(ReqlRuntimeError);

ReqlQueryPrinter = (function() {
  var carrotMarker, carrotify, composeCarrots, composeTerm, joinTree;

  function ReqlQueryPrinter() {}

  ReqlQueryPrinter.prototype.printQuery = function(term) {
    var tree;
    tree = composeTerm(term);
    return joinTree(tree);
  };

  composeTerm = function(term) {
    var arg, args, key, optargs, ref;
    args = (function() {
      var j, len, ref, results;
      ref = term.args;
      results = [];
      for (j = 0, len = ref.length; j < len; j++) {
        arg = ref[j];
        results.push(composeTerm(arg));
      }
      return results;
    })();
    optargs = {};
    ref = term.optargs;
    for (key in ref) {
      if (!hasProp.call(ref, key)) continue;
      arg = ref[key];
      optargs[key] = composeTerm(arg);
    }
    return term.compose(args, optargs);
  };

  ReqlQueryPrinter.prototype.printCarrots = function(term, frames) {
    var tree;
    if (frames.length === 0) {
      tree = [carrotify(composeTerm(term))];
    } else {
      tree = composeCarrots(term, frames);
    }
    return (joinTree(tree)).replace(/[^\^]/g, ' ');
  };

  composeCarrots = function(term, frames) {
    var arg, args, frame, i, key, optargs, ref;
    frame = frames.shift();
    args = (function() {
      var j, len, ref, results;
      ref = term.args;
      results = [];
      for (i = j = 0, len = ref.length; j < len; i = ++j) {
        arg = ref[i];
        if (frame === i) {
          results.push(composeCarrots(arg, frames));
        } else {
          results.push(composeTerm(arg));
        }
      }
      return results;
    })();
    optargs = {};
    ref = term.optargs;
    for (key in ref) {
      if (!hasProp.call(ref, key)) continue;
      arg = ref[key];
      if (frame === key) {
        optargs[key] = composeCarrots(arg, frames);
      } else {
        optargs[key] = composeTerm(arg);
      }
    }
    if (frame != null) {
      return term.compose(args, optargs);
    } else {
      return carrotify(term.compose(args, optargs));
    }
  };

  carrotMarker = {};

  carrotify = function(tree) {
    return [carrotMarker, tree];
  };

  joinTree = function(tree) {
    var j, len, str, term;
    str = '';
    for (j = 0, len = tree.length; j < len; j++) {
      term = tree[j];
      if (Array.isArray(term)) {
        if (term.length === 2 && term[0] === carrotMarker) {
          str += (joinTree(term[1])).replace(/./g, '^');
        } else {
          str += joinTree(term);
        }
      } else {
        str += term;
      }
    }
    return str;
  };

  return ReqlQueryPrinter;

})();

module.exports = {
  ReqlError: ReqlError,
  ReqlCompileError: ReqlCompileError,
  RqlCompileError: ReqlCompileError,
  ReqlServerCompileError: ReqlServerCompileError,
  ReqlDriverCompileError: ReqlDriverCompileError,
  RqlClientError: ReqlDriverError,
  ReqlRuntimeError: ReqlRuntimeError,
  RqlRuntimeError: ReqlRuntimeError,
  RqlServerError: ReqlRuntimeError,
  ReqlQueryLogicError: ReqlQueryLogicError,
  ReqlNonExistenceError: ReqlNonExistenceError,
  ReqlResourceLimitError: ReqlResourceLimitError,
  ReqlUserError: ReqlUserError,
  ReqlInternalError: ReqlInternalError,
  ReqlTimeoutError: ReqlTimeoutError,
  ReqlAvailabilityError: ReqlAvailabilityError,
  ReqlOpFailedError: ReqlOpFailedError,
  ReqlOpIndeterminateError: ReqlOpIndeterminateError,
  ReqlPermissionError: ReqlPermissionError,
  ReqlDriverError: ReqlDriverError,
  RqlDriverError: ReqlDriverError,
  ReqlAuthError: ReqlAuthError,
  printQuery: ReqlQueryPrinter.prototype.printQuery
};
