function getType(value) {
  return Object.prototype.toString.call(value).slice(8, -1)
}

class Task {
  constructor({ maxParallel }) {
    this.maxParallel = maxParallel
    this.runningTotal = 0
    this.storage = []
    this.resultCb = this.resultCb.bind(this)
  }

  push(mission, cb) {
    this.storage.push({mission, cb})
    this.run()
  }

  resultCb() {
    this.runningTotal--
    this.run()
  }

  run() {
    if (this.storage.length === 0 ||
      this.maxParallel <= this.runningTotal)
      return;
    
    this.runningTotal++

    let {mission: fn, cb} = this.storage.shift()
    let type = getType(fn)
    
    let promise = 
      type === 'Function' ? Promise.resolve(fn()) :
        type === 'Promise' ? fn :
          type === 'AsyncFunction' ? fn() : Promise.resolve(fn)

    promise.then(data => {
      cb && cb(data)
      this.resultCb()
    }).catch(error => {
      cb && cb()
      this.resultCb()
    })

    this.run()
  }
}

export default Task