/*
 * Tugas Besar 3 WBD - AMEN
 */

'use strict'

// Utilities.

let index = function (id, locations) {
  for (let location of locations) {
    let ids = this.locations[location]

    if (!ids) {
      ids = new Set()
      this.locations[location] = ids
    }

    ids.add(id)
  }
}

let unindex = function (id, locations) {
  for (let location of locations) {
    let ids = this.locations[location]

    if (ids) {
      ids.delete(id)
    }
  }
}

// Main routine.

class Hub {
  constructor () {
    this.drivers = {}
    this.locations = {}

    let indexLambda = index.bind(this)
    let unindexLambda = unindex.bind(this)

    this.waitAsync = async (id, locations, rejectFunc) => {
      let promise = new Promise((resolve, reject) => {
        this.drivers[id] = {
          resolve: resolve,
          reject: reject
        }

        // Pass reject function.
        if (rejectFunc) {
          rejectFunc(reject)
        }

        // Index locations.
        indexLambda(id, locations)
      })

      try {
        return await promise
      } finally {
        // Remove indexed locations.
        unindexLambda(id, locations)

        delete this.drivers[id]
      }
    }
  }

  filter (location) {
    return [...this.locations[location] || []]
  }

  pick (id, userId) {
    let handle = this.drivers[id]

    if (handle) {
      handle.resolve(userId)
      return true
    }

    return false
  }

  reject (id, reason) {
    let handle = this.drivers[id]

    if (handle) {
      handle.reject(reason)
      return true
    }

    return false
  }
}

module.exports = new Hub()