const http = require('http')
const https = require('https')

// GET YOUR OWN AT: https://openweathermap.org/appid
const APP_KEY = require('fs').readFileSync(__dirname + '/.key', {
  encoding: 'utf-8',
  flag: 'r'
}).trim()

const LISTEN = '8000'
const HOST = '0.0.0.0'

const REGEXP = {
  URL: /^\/[\d]{1,8}$/
}

const API = {
  // Define max 60 calls per 1 Minute
  MAX_CALLS: 60,
  INTERVAL: 1000 * 60, // 1 Minute
  current_calls: 0,
  last_reset: Date.now(),
}

const CACHE = {}
const MAX_AGE = 60 * 1000 // 1 Minute
const LAST_UPDATE_KEY = 'last_update'

function getForZip(zip) {
  return new Promise((resolve, reject) => {

    // If interval is over, reset max count
    if (Date.now() - API.last_reset > API.INTERVAL) {
      API.last_reset = Date.now()
      API.current_calls = 0
    }

    // Check if too many calls were already made
    if (API.current_calls > API.MAX_CALLS)
      resolve()

    API.current_calls++;

    // Make the call
    https.get({
      host: 'api.openweathermap.org',
      path: `/data/2.5/forecast?APPID=${APP_KEY}&zip=${zip},DE&units=metric`,
      timeout: 15 * 1000,
    }, res => {
      res.setEncoding('utf8')
      let body = ''
      res.on('data', data => {
        body += data
      })
      res.on('end', () => {
        const data = JSON.parse(body)
        data[LAST_UPDATE_KEY] = Date.now()
        resolve(data)
      })
    })

  })
}

function getUrlFromPath(path) {
  // Check if url is valid
  if (!REGEXP.URL.test(path))
    return false
  else
    // Exctract ZIP code
    return path.replace('/', '')
}

const server = http.createServer(async (req, res) => {

  const zip = getUrlFromPath(req.url)
  // Check if url is valid
  if (zip === false) {
    res.writeHead(400, {})
    res.end()
    return
  }

  // If there is no cached version, get it
  // If the last cached version is older than MAX_AGE, get it
  if (CACHE[zip] === undefined || Date.now() - CACHE[zip][LAST_UPDATE_KEY] > MAX_AGE)
    CACHE[zip] = await getForZip(zip)

  res.writeHead(200, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*'
  })
  res.write(JSON.stringify(CACHE[zip] || {}))
  res.end()
})

function exit() {
  console.log('Bye Bye')
  server.close()
}

function start() {
  console.log(`Started server on: ${LISTEN}. Using Key: ${APP_KEY}`)
  server.listen(LISTEN, HOST)
}

// Register exit function
process.on('exit', exit)
process.on('SIGINT', exit)
process.on('SIGQUIT', exit)
process.on('SIGTERM', exit)
process.on('uncaughtException', exit)

start()