var constants=require("fs-constants"),eos=require("end-of-stream"),util=require("util"),alloc=require("buffer-alloc"),toBuffer=require("to-buffer"),Readable=require("readable-stream").Readable,Writable=require("readable-stream").Writable,StringDecoder=require("string_decoder").StringDecoder,headers=require("./headers"),DMODE=parseInt("755",8),FMODE=parseInt("644",8),END_OF_TAR=alloc(1024),noop=function(){},overflow=function(e,t){(t&=511)&&e.push(END_OF_TAR.slice(0,512-t))};function modeToType(e){switch(e&constants.S_IFMT){case constants.S_IFBLK:return"block-device";case constants.S_IFCHR:return"character-device";case constants.S_IFDIR:return"directory";case constants.S_IFIFO:return"fifo";case constants.S_IFLNK:return"symlink"}return"file"}var Sink=function(e){Writable.call(this),this.written=0,this._to=e,this._destroyed=!1};util.inherits(Sink,Writable),Sink.prototype._write=function(e,t,i){if(this.written+=e.length,this._to.push(e))return i();this._to._drain=i},Sink.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var LinkSink=function(){Writable.call(this),this.linkname="",this._decoder=new StringDecoder("utf-8"),this._destroyed=!1};util.inherits(LinkSink,Writable),LinkSink.prototype._write=function(e,t,i){this.linkname+=this._decoder.write(e),i()},LinkSink.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var Void=function(){Writable.call(this),this._destroyed=!1};util.inherits(Void,Writable),Void.prototype._write=function(e,t,i){i(new Error("No body allowed for this entry"))},Void.prototype.destroy=function(){this._destroyed||(this._destroyed=!0,this.emit("close"))};var Pack=function(e){if(!(this instanceof Pack))return new Pack(e);Readable.call(this,e),this._drain=noop,this._finalized=!1,this._finalizing=!1,this._destroyed=!1,this._stream=null};util.inherits(Pack,Readable),Pack.prototype.entry=function(e,t,i){if(this._stream)throw new Error("already piping an entry");if(!this._finalized&&!this._destroyed){"function"==typeof t&&(i=t,t=null),i||(i=noop);var n=this;if(e.size&&"symlink"!==e.type||(e.size=0),e.type||(e.type=modeToType(e.mode)),e.mode||(e.mode="directory"===e.type?DMODE:FMODE),e.uid||(e.uid=0),e.gid||(e.gid=0),e.mtime||(e.mtime=new Date),"string"==typeof t&&(t=toBuffer(t)),Buffer.isBuffer(t))return e.size=t.length,this._encode(e),this.push(t),overflow(n,e.size),process.nextTick(i),new Void;if("symlink"===e.type&&!e.linkname){var r=new LinkSink;return eos(r,function(t){if(t)return n.destroy(),i(t);e.linkname=r.linkname,n._encode(e),i()}),r}if(this._encode(e),"file"!==e.type&&"contiguous-file"!==e.type)return process.nextTick(i),new Void;var s=new Sink(this);return this._stream=s,eos(s,function(t){return n._stream=null,t?(n.destroy(),i(t)):s.written!==e.size?(n.destroy(),i(new Error("size mismatch"))):(overflow(n,e.size),n._finalizing&&n.finalize(),void i())}),s}},Pack.prototype.finalize=function(){this._stream?this._finalizing=!0:this._finalized||(this._finalized=!0,this.push(END_OF_TAR),this.push(null))},Pack.prototype.destroy=function(e){this._destroyed||(this._destroyed=!0,e&&this.emit("error",e),this.emit("close"),this._stream&&this._stream.destroy&&this._stream.destroy())},Pack.prototype._encode=function(e){if(!e.pax){var t=headers.encode(e);if(t)return void this.push(t)}this._encodePax(e)},Pack.prototype._encodePax=function(e){var t=headers.encodePax({name:e.name,linkname:e.linkname,pax:e.pax}),i={name:"PaxHeader",mode:e.mode,uid:e.uid,gid:e.gid,size:t.length,mtime:e.mtime,type:"pax-header",linkname:e.linkname&&"PaxHeader",uname:e.uname,gname:e.gname,devmajor:e.devmajor,devminor:e.devminor};this.push(headers.encode(i)),this.push(t),overflow(this,t.length),i.size=e.size,i.type=e.type,this.push(headers.encode(i))},Pack.prototype._read=function(e){var t=this._drain;this._drain=noop,t()},module.exports=Pack;