var util=require("util"),bl=require("bl"),xtend=require("xtend"),headers=require("./headers"),Writable=require("readable-stream").Writable,PassThrough=require("readable-stream").PassThrough,noop=function(){},overflow=function(e){return(e&=511)&&512-e},emptyStream=function(e,t){var i=new Source(e,t);return i.end(),i},mixinPax=function(e,t){return t.path&&(e.name=t.path),t.linkpath&&(e.linkname=t.linkpath),t.size&&(e.size=parseInt(t.size,10)),e.pax=t,e},Source=function(e,t){this._parent=e,this.offset=t,PassThrough.call(this)};util.inherits(Source,PassThrough),Source.prototype.destroy=function(e){this._parent.destroy(e)};var Extract=function(e){if(!(this instanceof Extract))return new Extract(e);Writable.call(this,e),e=e||{},this._offset=0,this._buffer=bl(),this._missing=0,this._partial=!1,this._onparse=noop,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var t=this,i=t._buffer,r=function(){t._continue()},n=function(e){if(t._locked=!1,e)return t.destroy(e);t._stream||r()},s=function(){t._stream=null;var e=overflow(t._header.size);e?t._parse(e,a):t._parse(512,u),t._locked||r()},a=function(){t._buffer.consume(overflow(t._header.size)),t._parse(512,u),r()},o=function(){var e=t._header.size;t._paxGlobal=headers.decodePax(i.slice(0,e)),i.consume(e),s()},h=function(){var e=t._header.size;t._pax=headers.decodePax(i.slice(0,e)),t._paxGlobal&&(t._pax=xtend(t._paxGlobal,t._pax)),i.consume(e),s()},_=function(){var r=t._header.size;this._gnuLongPath=headers.decodeLongPath(i.slice(0,r),e.filenameEncoding),i.consume(r),s()},l=function(){var r=t._header.size;this._gnuLongLinkPath=headers.decodeLongPath(i.slice(0,r),e.filenameEncoding),i.consume(r),s()},u=function(){var a,c=t._offset;try{a=t._header=headers.decode(i.slice(0,512),e.filenameEncoding)}catch(e){t.emit("error",e)}return i.consume(512),a?"gnu-long-path"===a.type?(t._parse(a.size,_),void r()):"gnu-long-link-path"===a.type?(t._parse(a.size,l),void r()):"pax-global-header"===a.type?(t._parse(a.size,o),void r()):"pax-header"===a.type?(t._parse(a.size,h),void r()):(t._gnuLongPath&&(a.name=t._gnuLongPath,t._gnuLongPath=null),t._gnuLongLinkPath&&(a.linkname=t._gnuLongLinkPath,t._gnuLongLinkPath=null),t._pax&&(t._header=a=mixinPax(a,t._pax),t._pax=null),t._locked=!0,a.size&&"directory"!==a.type?(t._stream=new Source(t,c),t.emit("entry",a,t._stream,n),t._parse(a.size,s),void r()):(t._parse(512,u),void t.emit("entry",a,emptyStream(t,c),n))):(t._parse(512,u),void r())};this._onheader=u,this._parse(512,u)};util.inherits(Extract,Writable),Extract.prototype.destroy=function(e){this._destroyed||(this._destroyed=!0,e&&this.emit("error",e),this.emit("close"),this._stream&&this._stream.emit("close"))},Extract.prototype._parse=function(e,t){this._destroyed||(this._offset+=e,this._missing=e,t===this._onheader&&(this._partial=!1),this._onparse=t)},Extract.prototype._continue=function(){if(!this._destroyed){var e=this._cb;this._cb=noop,this._overflow?this._write(this._overflow,void 0,e):e()}},Extract.prototype._write=function(e,t,i){if(!this._destroyed){var r=this._stream,n=this._buffer,s=this._missing;if(e.length&&(this._partial=!0),e.length<s)return this._missing-=e.length,this._overflow=null,r?r.write(e,i):(n.append(e),i());this._cb=i,this._missing=0;var a=null;e.length>s&&(a=e.slice(s),e=e.slice(0,s)),r?r.end(e):n.append(e),this._overflow=a,this._onparse()}},Extract.prototype._final=function(e){if(this._partial)return this.destroy(new Error("Unexpected end of data"));e()},module.exports=Extract;