'use strict';
var createHash = require('sha.js')

var md5 = require('./md5')
var rmd160 = require('ripemd160')
var Transform = require('stream').Transform;
var inherits = require('inherits')

module.exports = function (alg) {
  if('md5' === alg) return new HashNoConstructor(md5)
  if('rmd160' === alg) return new HashNoConstructor(rmd160)
  return new Hash(createHash(alg))
}
inherits(HashNoConstructor, Transform)

function HashNoConstructor(hash) {
  Transform.call(this);
  this._hash = hash
  this.buffers = []
}

HashNoConstructor.prototype._transform = function (data, _, done) {
  this.buffers.push(data)
  done()
}
HashNoConstructor.prototype._flush = function (done) {
  var buf = Buffer.concat(this.buffers)
  var r = this._hash(buf)
  this.buffers = null
  this.push(r)
  done()
}
HashNoConstructor.prototype.update = function (data, enc) {
  this.write(data, enc)
  return this
}

HashNoConstructor.prototype.digest = function (enc) {
  this.end()
  var outData = new Buffer('')
  var chunk
  while ((chunk = this.read())) {
    outData = Buffer.concat([outData, chunk])
  }
  if (enc) {
    outData = outData.toString(enc)
  }
  return outData
}

inherits(Hash, Transform)

function Hash(hash) {
  Transform.call(this);
  this._hash = hash
}

Hash.prototype._transform = function (data, _, done) {
  this._hash.update(data)
  done()
}
Hash.prototype._flush = function (done) {
  this.push(this._hash.digest())
  this._hash = null
  done()
}
Hash.prototype.update = function (data, enc) {
  this.write(data, enc)
  return this
}

Hash.prototype.digest = function (enc) {
  this.end()
  var outData = new Buffer('')
  var chunk
  while ((chunk = this.read())) {
    outData = Buffer.concat([outData, chunk])
  }
  if (enc) {
    outData = outData.toString(enc)
  }
  return outData
}