/**
 * node-archiver
 *
 * Copyright (c) 2012-2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-archiver/blob/master/LICENSE-MIT
 */
var fs = require('fs');
var inherits = require('util').inherits;
var Transform = require('readable-stream').Transform;

var async = require('async');

var util = require('../../util');

var Archiver = module.exports = function(options) {
  options = this.options = util.defaults(options, {
    highWaterMark: 1024 * 1024
  });

  Transform.call(this, options);

  this._entries = [];
  this._module = false;
  this._pointer = 0;

  this._queue = async.queue(this._onQueueTask.bind(this), 1);
  this._queue.drain = this._onQueueDrain.bind(this);

  this._state = {
    finalize: false,
    finalized: false,
    modulePiped: false
  };
};

inherits(Archiver, Transform);

Archiver.prototype._append = function(filepath, data) {
  data = data || {};

  if (!data.name) {
    data.name = filepath;
  }

  data.sourcePath = filepath;

  this._queue.push({
    data: data,
    source: null,
    deferredStat: true,
    filepath: filepath
  });
};

Archiver.prototype._moduleAppend = function(source, data, callback) {
  this._module.append(source, data, callback);
};

Archiver.prototype._moduleFinalize = function() {
  this._state.finalized = true;

  if (typeof this._module.finalize === 'function') {
    this._module.finalize();
  } else if (typeof this._module.end === 'function') {
    this._module.end();
  } else {
    this.emit('error', new Error('format module missing finalize and end method'));
  }
};

Archiver.prototype._moduleSupports = function(key) {
  this._module.supports = util.defaults(this._module.supports, {
    directory: false
  });

  return this._module.supports[key];
};

Archiver.prototype._normalizeEntryData = function(data, stats) {
  stats = stats || false;
  data = util.defaults(data, {
    type: 'file',
    name: null,
    date: null,
    mode: null,
    sourcePath: null
  });

  var isDir = data.type === 'directory';

  if (data.name) {
    data.name = util.sanitizePath(data.name);

    if (data.name.slice(-1) === '/') {
      isDir = true;
      data.type = 'directory';
    } else if (isDir) {
      data.name += '/';
    }
  }

  if (typeof data.mode === 'number') {
    data.mode &= 0777;
  } else if (stats) {
    data.mode = stats.mode & 0777;
  } else {
    data.mode = isDir ? 0755 : 0644;
  }

  if (stats && data.date === null) {
    data.date = stats.mtime;
  }

  data.date = util.dateify(data.date);

  data._stats = stats;

  return data;
};

Archiver.prototype._onModuleError = function(err) {
  this.emit('error', err);
};

Archiver.prototype._onQueueDrain = function() {
  if (this._state.finalize && !this._state.finalized && this._queue.idle()) {
    this._moduleFinalize();
  }
};

Archiver.prototype._onQueueTask = function(task, callback) {
  var afterAppend = function(err, entry) {
    if (err) {
      this.emit('error', err);
      callback();
      return;
    }

    entry = entry || task.data;

    this.emit('entry', entry);
    this._entries.push(entry);

    callback();
  }.bind(this);

  var afterStat = function(err, stats) {
    if (err) {
      this.emit('error', err);
      callback();
      return;
    }

    task = this._updateQueueTaskWithStats(task, stats);

    if (task.source !== null) {
      this._moduleAppend(task.source, task.data, afterAppend);
    } else {
      this.emit('error', new Error('unsupported entry: ' + task.filepath));
      callback();
      return;
    }
  }.bind(this);

  if (task.deferredStat) {
    fs.stat(task.filepath, afterStat);
  } else {
    this._moduleAppend(task.source, task.data, afterAppend);
  }
};

Archiver.prototype._updateQueueTaskWithStats = function(task, stats) {
  if (stats.isFile()) {
    task.data.type = 'file';
    task.data.sourceType = 'stream';
    task.source = util.lazyReadStream(task.filepath);
  } else if (stats.isDirectory() && this._moduleSupports('directory')) {
    task.data.name = util.trailingSlashIt(task.data.name);
    task.data.type = 'directory';
    task.data.sourcePath = util.trailingSlashIt(task.filepath);
    task.data.sourceType = 'buffer';
    task.source = new Buffer(0);
  } else {
    return task;
  }

  task.data = this._normalizeEntryData(task.data, stats);
  return task;
};

Archiver.prototype._pipeModuleOutput = function() {
  this._module.on('error', this._onModuleError.bind(this));
  this._module.pipe(this);

  this._state.modulePiped = true;
};

Archiver.prototype._processFile = function(source, data, callback) {
  this.emit('error', new Error('method not implemented'));
};

Archiver.prototype._transform = function(chunk, encoding, callback) {
  if (chunk) {
    this._pointer += chunk.length;
  }

  callback(null, chunk);
};

Archiver.prototype.append = function(source, data) {
  if (this._state.finalize) {
    this.emit('error', new Error('unable to append after calling finalize.'));
    return this;
  }

  data = this._normalizeEntryData(data);

  if (typeof data.name !== 'string' || data.name.length === 0) {
    this.emit('error', new Error('entry name must be a non-empty string value'));
    return this;
  }

  if (data.type === 'directory' && !this._moduleSupports('directory')) {
    this.emit('error', new Error('entries of "directory" type not currently supported by this module'));
    return this;
  }

  source = util.normalizeInputSource(source);

  if (Buffer.isBuffer(source)) {
    data.sourceType = 'buffer';
  } else if (util.isStream(source)) {
    data.sourceType = 'stream';
  } else {
    this.emit('error', new Error('input source must be valid Stream or Buffer instance'));
    return this;
  }

  this._queue.push({
    data: data,
    source: source
  });

  return this;
};

Archiver.prototype.bulk = function(mappings) {
  if (this._state.finalize) {
    this.emit('error', new Error('unable to append after calling finalize.'));
    return this;
  }

  if (!Array.isArray(mappings)) {
    mappings = [mappings];
  }

  var self = this;
  var files = util.file.normalizeFilesArray(mappings);

  files.forEach(function(file){
    var isExpandedPair = file.orig.expand || false;
    var fileData = file.data || {};

    file.src.forEach(function(filepath) {
      var data = util._.extend({}, fileData);
      var name = isExpandedPair ? file.dest : util.unixifyPath(file.dest || '', filepath);

      if (name === '.') {
        return;
      }

      data.name = name;
      self._append(filepath, data);
    });
  });

  return this;
};

Archiver.prototype.file = function(filepath, data) {
  if (this._state.finalize) {
    this.emit('error', new Error('unable to append after calling finalize.'));
    return this;
  }

  if (typeof filepath !== 'string' || filepath.length === 0) {
    this.emit('error', new Error('filepath must be a non-empty string value'));
    return this;
  }

  this._append(filepath, data);

  return this;
};

Archiver.prototype.finalize = function() {
  this._state.finalize = true;

  if (this._queue.idle()) {
    this._moduleFinalize();
  }

  return this;
};

Archiver.prototype.setModule = function(module) {
  if (this._state.modulePiped) {
    this.emit('error', new Error('format module already set'));
    return;
  }

  this._module = module;
  this._pipeModuleOutput();
};

Archiver.prototype.pointer = function() {
  return this._pointer;
};