'use strict'

// dependencies
const request = require('request')
const requestPromise = require('request-promise')
const Bottleneck = require('bottleneck')

module.exports = class WmataWrapper {
    constructor (options, config) {
      // config contains API/endpoint-specific configuration settings
      this.set(config) // set given config to this.config
      // options includes the API key and optional behaviors
      if (options) {
        this.API_KEY = options.apiKey || this.config.DEMO_KEY
        this.debugMode = options.debugMode
        this.ttl = options.ttl || this.config.TIME_TO_LIVE
      } else {
        this.API_KEY = this.config.DEMO_KEY
        this.ttl = this.config.TIME_TO_LIVE
        console.log(`Using defaults for ${this.config.WRAPPER_NAME} APIs.`)
      }
      console.log('TTL', this.ttl, this.config)
      if (!this.API_KEY) {
        console.error('API key not supplied.')
      }
      this.limiter = new Bottleneck(this.config.MAX_CALLS_PER, this.config.INTERVAL)
    }

    set (config) { // set this instance's config to given config
      this.config = config // child classes may overwrite this and assign a specified config
    }

    get realTimeFeeds () { return this.config.REAL_TIME_FEEDS }
    get feed () { return this.config.FEEDS }

    addTimestamp (responseJson) {
      responseJson.timestamp = Date.now()
      for (let i in this.realTimeFeeds) {
        if (responseJson[this.realTimeFeeds[i]]) {
          responseJson.ttl = this.ttl || this.config.TIME_TO_LIVE
          break
        }
      }
      if (this.debugMode) {
        responseJson.captranDebug = {
          debugMode: this.debugMode,
          queryQueueLength: this.queryQueueLength,
          timestamp: responseJson.timestamp,
          ttl: responseJson.ttl
        }
      }
      return responseJson
    }

    renderQueryUrl (params, apiKey) {
      let url = this.feed[params.api]
      if (!url) {
        throw new Error(`Ohnoes, ${params.api} isn't a valid API`)
      }
      let query = Object.keys(params)
        .filter(key => key !== 'api')
        .map(key => `${key}=${params[key]}`)
        .join('&')
      if (query !== '') query += '&'
      return encodeURI(`${url}?` + query + `${this.config.AUTH_TOKEN_FIELD}=${apiKey || this.API_KEY}`)
    }

    query (params, callback) {
      if (typeof (params) !== 'object' || !params.api) {
        throw new Error(`Ohnoes, invalid query params: ${params}`)
      }
      return callback // if
        ? this.limiter.submit( // returns true if successful, invokes callback
          request,
          this.renderQueryUrl(params),
          (err, response) => callback(err, this.addTimestamp(JSON.parse(response)).bind(this))
          )
        : this.limiter // or returns promising version
          .schedule(requestPromise, this.renderQueryUrl(params))
          .then(JSON.parse)
          .then(this.addTimestamp.bind(this))
    }

    queryBusPositions (callback) { // shortcut
      return this.query({
        api: 'busPositions'
      })
    }

    get queryQueueLength () {
      return this.limiter.nbQueued()
    }
    get queryQueueIsClear () {
      return this.limiter.check()
    }
}

@@ -423,16 +423,17 @@
     if (
+!
 options)
@@ -433,24 +433,127 @@
 ptions) %7B%0A  
+      options = %7B%7D%0A        console.log(%60Using defaults for $%7Bthis.config.WRAPPER_NAME%7D APIs.%60)%0A      %7D%0A
       this.A
@@ -602,26 +602,24 @@
 O_KEY%0A      
-  
 this.debugMo
@@ -640,19 +640,26 @@
 ebugMode
-%0A  
+ %7C%7C false%0A
       th
@@ -717,287 +717,80 @@
     
-%7D else %7B%0A        this.API_KEY = this.config.DEMO_KEY%0A        this.ttl = this.config.TIME_TO_LIVE%0A        console.log(%60Using defaults for $%7Bthis.config.WRAPPER_NAME%7D APIs.%60)%0A      %7D%0A      console.log('TTL', this.ttl, this.config)%0A      if (!this.API_KEY) %7B%0A        console.error('
+if (!this.API_KEY) %7B%0A        console.error(%60$%7Bthis.config.WRAPPER_NAME%7D 
 API 
@@ -806,17 +806,17 @@
 upplied.
-'
+%60
 )%0A      

Streamline initialization of default options in WMATA wrapper