/*
 * routing-stream.js: A Stream focused on connecting an arbitrary RequestStream and
 * ResponseStream through a given Router.
 *
 * (C) 2011, Charlie Robbins & the Contributors
 * MIT LICENSE
 *
 */

var util = require('util'),
    union = require('./index'),
    RequestStream = require('./request-stream'),
    ResponseStream = require('./response-stream');

//
// ### function RoutingStream (options)
//
//
var RoutingStream = module.exports = function (options) {
  options = options || {};
  RequestStream.call(this, options);

  this.before = options.before || [];
  this.after = options.after || [];
  this.response = options.response || options.res;
  this.headers = options.headers || {
    'x-powered-by': 'union ' + union.version
  };

  this.target = new ResponseStream({
    response: this.response,
    headers: this.headers
  });

  this.once('pipe', this.route);
};

util.inherits(RoutingStream, RequestStream);

//
// Called when this instance is piped to **by another stream**
//
RoutingStream.prototype.route = function (req) {
  //
  // When a `RoutingStream` is piped to:
  //
  // 1. Setup the pipe-chain between the `after` middleware, the abstract response
  //    and the concrete response.
  // 2. Attempt to dispatch to the `before` middleware, which represent things such as
  //    favicon, static files, application routing.
  // 3. If no match is found then pipe to the 404Stream
  //
  var self = this,
      after,
      error,
      i;

  //
  // Don't allow `this.target` to be writable on HEAD requests
  //
  this.target.writable = req.method !== 'HEAD';

  //
  // 1. Setup the pipe-chain between the `after` middleware, the abstract response
  //    and the concrete response.
  //
  after = [this.target].concat(this.after, this.response);
  for (i = 0; i < after.length - 1; i++) {
    //
    // attach req and res to all streams
    //
    after[i].req     = req;
    after[i + 1].req = req;
    after[i].res     = this.response;
    after[i + 1].res = this.response;
    after[i].pipe(after[i + 1]);

    //
    // prevent multiple responses and memory leaks
    //
    after[i].on('error', this.onError);
  }

  //
  // Helper function for dispatching to the 404 stream.
  //
  function notFound() {
    error = new Error('Not found');
    error.status = 404;
    self.onError(error);
  }

  //
  // 2. Attempt to dispatch to the `before` middleware, which represent things such as
  //    favicon, static files, application routing.
  //
  (function dispatch(i) {
    if (self.target.modified) {
      return;
    }
    else if (++i === self.before.length) {
      //
      // 3. If no match is found then pipe to the 404Stream
      //
      return notFound();
    }

    self.target.once('next', dispatch.bind(null, i));
    if (self.before[i].length === 3) {
      self.before[i](self, self.target, function (err) {
        if (err) {
          self.onError(err);
        } else {
          self.target.emit('next');
        }
      });
    }
    else {
      self.before[i](self, self.target);
    }
  })(-1);
};

RoutingStream.prototype.onError = function (err) {
  this.emit('error', err);
};
