'use strict'

var env // must include WMATA API developer key `env.WMATA_KEY`

try {
  env = require('./env')
} catch (localEnvJsNotPresentException) {
  env = process.env
}

// According to WMATA, "Default tier sufficient for most casual developers.
// Rate limited to 10 calls/second and 50,000 calls per day."
// https://developer.wmata.com/Products

// API docs say most real-time info is updated every 20 to 30 seconds

const Bottleneck = require('bottleneck')
var limiter = new Bottleneck(10, 1000)

const request = require('request-promise')
const busServicesRequestUrl = 'https://api.wmata.com/Bus.svc/json/'
const requestUrl = {
  forBus: {
    stops: busServicesRequestUrl + 'jStops',
    positions: busServicesRequestUrl + 'jBusPositions',
    routeDetails: busServicesRequestUrl + 'jRouteDetails',
    routes: busServicesRequestUrl + 'jRoutes',
    routeSchedule: busServicesRequestUrl + 'jRouteSchedule',
    stopSchedule: busServicesRequestUrl + 'jStopSchedule',
    arrivalPredictions: 'https://api.wmata.com/NextBusService.svc/json/jPredictions'
  }
}

// helpers
const renderUriWithParams = (uri, params, apiKey) => encodeURI(
    `${uri}?` +
    Object.keys(params).filter((key) =>
      params[key] !== null).map((key) => `${key}=${params[key]}`).join('&') +
        `&api_key=${apiKey || env.WMATA_KEY}`
  )

var callCount = 0 // FIXME perhaps this approach won't work

function incrementCallCount () {
  callCount++
  return callCount
}

function getCallCount () {
  return callCount
}

var callWmata = (endpoint, params, apiKey) => {
  incrementCallCount()
  // pre-limiter version:
  // return request(renderUriWithParams(endpoint, params, apiKey)).then(JSON.parse)
  return limiter.schedule(request, renderUriWithParams(endpoint, params, apiKey)).then(JSON.parse)
}

const busServices = { // API wrapper for bus services
  // # WMATA Bus Route and Stop Methods (JSON)
  // https://developer.wmata.com/docs/services/54763629281d83086473f231/operations/5476362a281d830c946a3d68

  // ## Bus Position

  getAllPositions: () => callWmata(requestUrl.forBus.positions, {}),

  getPositionsNear: (lat, long, radius) => callWmata(requestUrl.forBus.positions, {
    Lat: lat,
    Lon: long,
    Radius: radius
  }),

  getPositionsOnRoute: (routeId) => callWmata(requestUrl.forBus.positions, {
    RouteID: routeId
  }),

  // ## Path Details

  getRouteDetails: (routeId, date) => callWmata(requestUrl.forBus.routeDetails, {
    RouteID: routeId,
    Date: date // in YYYY-MM-DD format (optional)
  }),

  // ## Routes

  getRoutes: () => callWmata(requestUrl.forBus.routes),

  // ## Schedule

  getRouteSchedule: (routeId, date, includingVariations) => callWmata(requestUrl.forBus.routeSchedule, {
    RouteID: routeId,
    Date: date,
    // if omitted (i.e. null), omit, otherwise convert boolean to string "true" or "false"
    IncludingVariations: includingVariations === null ? null : (includingVariations ? 'true' : 'false')
    // not sure if WMATA's API considers true or false the default if omitted
  }),

  // ## Schedule at Stop

  getStopSchedule: (stopId, date) => callWmata(requestUrl.forBus.stopSchedule, {
    StopID: stopId,
    Date: date // in YYYY-MM-DD format
  }),

  // ## Stop Search

  getAllStops: () => callWmata(requestUrl.forBus.stops, {}),

  getStops: (lat, long, radius) => callWmata(requestUrl.forBus.stops, {
    Lat: lat,
    Lon: long,
    Radius: radius
  }),

  // hard-coded shortcut for development
  getPentagonStops: () => callWmata(requestUrl.forBus.stops, {
    Lat: 38.8690011,
    Lon: -77.0544217,
    Radius: 500
  }),

  // # Real-Time Bus Predictions (JSON)
  // https://developer.wmata.com/docs/services/5476365e031f590f38092508/operations/5476365e031f5909e4fe331d

  getArrivalPredictions: (stopId) => {
    if (stopId === '0') {
      let msg = 'Cant look up bus stop without id'
      console.error(msg)
      return Promise.reject(msg)
    } else return callWmata(requestUrl.forBus.arrivalPredictions, { StopID: stopId })
  }
}

// const railService = {
//   // TODO
// }
//
// const incidents = {
//   // TODO
// }

module.exports = {

  ping: (request) => JSON.parse('{ "body": "pong"}'),

  // WMATA Bus Route and Stop Methods (JSON)
  metrobus: busServices,

  // WMATA Rail Station Information (JSON)
  // metrorail: railService,

  // helper function for rendering request URL with query parameters
  renderUriWithParams: renderUriWithParams, // exported for testing

  incrementCallCount: incrementCallCount,

  getCallCount: getCallCount,

  requestUrl: requestUrl

}

@@ -54,16 +54,29 @@
 oper key
+, accessed as
  %60env.WM
@@ -90,16 +90,69 @@
 %60%0A%0Atry %7B
+ // look for environment config file on local machine
 %0A  env =
@@ -210,16 +210,50 @@
 ption) %7B
+ // otherwise use environemnt vars
 %0A  env =
@@ -1171,18 +1171,84 @@
 / helper
+ function to craft request urls with query params for API endpoint
 s%0A
-
 const re
@@ -1500,376 +1500,56 @@
 call
-Count = 0 // FIXME perhaps this approach won't work%0A%0Afunction incrementCallCount () %7B%0A  callCount++%0A  return callCount%0A%7D%0A%0Afunction getCallCount () %7B%0A  return callCount%0A%7D%0A%0Avar callWmata = (endpoint, params, apiKey) =%3E %7B%0A  incrementCallCount()%0A  // pre-limiter version:%0A  // return request(renderUriWithParams(endpoint, params, apiKey)).then(JSON.parse)%0A  return limiter
+Wmata = (endpoint, params, apiKey) =%3E limiter%0A  
 .sch
@@ -1609,16 +1609,19 @@
 apiKey))
+%0A  
 .then(JS
@@ -1629,18 +1629,16 @@
 N.parse)
-%0A%7D
 %0A%0Aconst 
@@ -4261,17 +4261,16 @@
 thParams
-,
  // expo
@@ -4291,106 +4291,6 @@
 ng%0A%0A
-  incrementCallCount: incrementCallCount,%0A%0A  getCallCount: getCallCount,%0A%0A  requestUrl: requestUrl%0A%0A
 %7D%0A

Clean up and comment before adding redis layer