
/**
 * Module dependencies.
 */

var util = require('util');
var mime = require('mime');
var FormData = require('form-data');
var PassThrough = require('readable-stream/passthrough');

/**
 * Initialize a new `Part` for the given `req`.
 *
 * @param {Request} req
 * @api public
 * @deprecated pass a readable stream in to `Request#attach()` instead
 */

var Part = function (req) {
  PassThrough.call(this);
  this._req = req;
  this._attached = false;
  this._name = null;
  this._type = null;
  this._header = null;
  this._filename = null;

  this.once('pipe', this._attach.bind(this));
};
Part = util.deprecate(Part, 'The `Part()` constructor is deprecated. ' +
   'Pass a readable stream in to `Request#attach()` instead.');

/**
 * Inherit from `PassThrough`.
 */

util.inherits(Part, PassThrough);

/**
 * Expose `Part`.
 */

module.exports = Part;

/**
 * Set header `field` to `val`.
 *
 * @param {String} field
 * @param {String} val
 * @return {Part} for chaining
 * @api public
 */

Part.prototype.set = function(field, val){
  //if (!this._header) this._header = {};
  //this._header[field] = val;
  //return this;
  throw new TypeError('setting custom form-data part headers is unsupported');
};

/**
 * Set _Content-Type_ response header passed through `mime.lookup()`.
 *
 * Examples:
 *
 *     res.type('html');
 *     res.type('.html');
 *
 * @param {String} type
 * @return {Part} for chaining
 * @api public
 */

Part.prototype.type = function(type){
  var lookup = mime.lookup(type);
  this._type = lookup;
  //this.set('Content-Type', lookup);
  return this;
};

/**
 * Set the "name" portion for the _Content-Disposition_ header field.
 *
 * @param {String} name
 * @return {Part} for chaining
 * @api public
 */

Part.prototype.name = function(name){
  this._name = name;
  return this;
};

/**
 * Set _Content-Disposition_ header field to _attachment_ with `filename`
 * and field `name`.
 *
 * @param {String} name
 * @param {String} filename
 * @return {Part} for chaining
 * @api public
 */

Part.prototype.attachment = function(name, filename){
  this.name(name);
  if (filename) {
    this.type(filename);
    this._filename = filename;
  }
  return this;
};

/**
 * Calls `FormData#append()` on the Request instance's FormData object.
 *
 * Gets called implicitly upon the first `write()` call, or the "pipe" event.
 *
 * @api private
 */

Part.prototype._attach = function(){
  if (this._attached) return;
  this._attached = true;

  if (!this._name) throw new Error('must call `Part#name()` first!');

  // add `this` Stream's readable side as a stream for this Part
  if (!this._req._formData) this._req._formData = new FormData();
  this._req._formData.append(this._name, this, {
    contentType: this._type,
    filename: this._filename
  });

  // restore PassThrough's default `write()` function now that we're setup
  this.write = PassThrough.prototype.write;
};

/**
 * Write `data` with `encoding`.
 *
 * @param {Buffer|String} data
 * @param {String} encoding
 * @return {Boolean}
 * @api public
 */

Part.prototype.write = function(){
  this._attach();
  return this.write.apply(this, arguments);
};
