var binary = require('binary');
var PullStream = require('../PullStream');
var unzip = require('./unzip');
var Promise = require('bluebird');
var BufferStream = require('../BufferStream');
var parseExtraField = require('../parseExtraField');
var Buffer = require('../Buffer');

var signature = Buffer.alloc(4);
signature.writeUInt32LE(0x06054b50,0);

module.exports = function centralDirectory(source) {
  var endDir = PullStream(),
      records = PullStream(),
      self = this,
      vars;

  return source.size()
    .then(function(size) {
      source.stream(size-40).pipe(endDir);
      return endDir.pull(signature);
    })
    .then(function() {
      return endDir.pull(22);
    })
    .then(function(data) {
      vars = binary.parse(data)
        .word32lu('signature')
        .word16lu('diskNumber')
        .word16lu('diskStart')
        .word16lu('numberOfRecordsOnDisk')
        .word16lu('numberOfRecords')
        .word32lu('sizeOfCentralDirectory')
        .word32lu('offsetToStartOfCentralDirectory')
        .word16lu('commentLength')
        .vars;

      source.stream(vars.offsetToStartOfCentralDirectory).pipe(records);

      vars.files = Promise.mapSeries(Array(vars.numberOfRecords),function() {
        return records.pull(46).then(function(data) {    
          var vars = binary.parse(data)
            .word32lu('signature')
            .word16lu('versionMadeBy')
            .word16lu('versionsNeededToExtract')
            .word16lu('flags')
            .word16lu('compressionMethod')
            .word16lu('lastModifiedTime')
            .word16lu('lastModifiedDate')
            .word32lu('crc32')
            .word32lu('compressedSize')
            .word32lu('uncompressedSize')
            .word16lu('fileNameLength')
            .word16lu('extraFieldLength')
            .word16lu('fileCommentLength')
            .word16lu('diskNumber')
            .word16lu('internalFileAttributes')
            .word32lu('externalFileAttributes')
            .word32lu('offsetToLocalFileHeader')
            .vars;

        return records.pull(vars.fileNameLength).then(function(fileNameBuffer) {
          vars.pathBuffer = fileNameBuffer;
          vars.path = fileNameBuffer.toString('utf8');
          vars.isUnicode = vars.flags & 0x11;
          return records.pull(vars.extraFieldLength);
        })
        .then(function(extraField) {
          vars.extra = parseExtraField(extraField, vars);
          return records.pull(vars.fileCommentLength);
        })
        .then(function(comment) {
          vars.comment = comment;
          vars.stream = function(_password) {
            return unzip(source, vars.offsetToLocalFileHeader,_password);
          };
          vars.buffer = function(_password) {
            return BufferStream(vars.stream(_password));
          };
          return vars;
        });
      });
    });

    return Promise.props(vars);
  });
};
