text: 'use strict';
  
  var inherits = require('util').inherits,
      EventEmitter = require('events').EventEmitter,
      debug = require('debug')('pool2');
  
  var _id = 0;
  
  // this has promisey semantics but can't really be replaced with a simple promise
  function ResourceRequest(timeout, callback) {
      if (typeof timeout === 'function') {
          callback = timeout;
          timeout = Infinity;
      }
      if (typeof callback !== 'function') {
          throw new Error('new ResourceRequest(): callback is required');
      }
      
      EventEmitter.call(this);
      
      this.id = _id++;
      this.ts = new Date();
      this.cb = callback;
      this.fulfilled = false;
      this.timer = null;
      
      debug('New ResourceRequest (id=%s, timeout=%s)', this.id, timeout);
      
      if (timeout !== Infinity) { this.setTimeout(timeout); }
  }
  inherits(ResourceRequest, EventEmitter);
  
  ResourceRequest.prototype.setTimeout = function (_duration) {
      if (_duration === Infinity) {
          debug('ResourceRequest: setTimeout called with Infinity: clearing timeout');
          this.clearTimeout();
          return;
      }
      
      var duration = parseInt(_duration, 10);
      
      if (isNaN(duration) || duration <= 0) {
          throw new Error('ResourceRequest.setTimeout(): invalid duration: ' + duration);
      }
      
      var now = new Date(),
          elapsed = now - this.ts;
      
      if (elapsed > duration) {
          setImmediate(this._rejectTimeout.bind(this));
      } else {
          this.timer = setTimeout(this._rejectTimeout.bind(this), duration - elapsed);
      }
  };
  ResourceRequest.prototype.clearTimeout = function () {
      debug('ResourceRequest: clearing timeout (id=%s)', this.id);
      clearTimeout(this.timer);
      this.timer = null;
  };
  ResourceRequest.prototype.resolve = function (res) {
      debug('ResourceRequest: resolve (id=%s)', this.id);
      this._fulfill(null, res);
  };
  ResourceRequest.prototype.reject = function (err) {
      debug('ResourceRequest: reject (id=%s)', this.id);
      this._fulfill(err);
  };
  ResourceRequest.prototype.abort = function (msg) {
      msg = msg || 'No reason given';
      
      debug('ResourceRequest: abort (id=%s)', this.id);
      this.reject(new Error('ResourceRequest aborted: ' + msg));
  };
  ResourceRequest.prototype._rejectTimeout = function () {
      debug('ResourceRequest: rejectTimeout (id=%s)', this.id);
      this.reject(new Error('ResourceRequest timed out'));
  };
  ResourceRequest.prototype._fulfill = function (err, res) {
      if (err !== null) {
          debug('ResourceRequest: fulfilling with error: %s (id=%s)', err.message, this.id);
          // ensure any error gets emitted
          this.emit('error', err);
      } else {
          debug('ResourceRequest: fulfilling with resource (id=%s)', this.id);
      }
      
      // if we've already fulfilled this request, don't try to do it again
      if (this.fulfilled) {
          debug('ResourceRequest: redundant fulfill, not calling callback (id=%s)', this.id);
          // but make sure somebody knows about it
          this.emit('error', new Error('ResourceRequest already fulfilled'));
          return;
      }
      
      this.fulfilled = true;
      this.clearTimeout();
      this.cb.apply(this, arguments);
  };
  
  module.exports = ResourceRequest;
  