import * as express from 'express'
import Prometheus = require('prom-client')

export class Metrics {
  private readonly _options: any
  public readonly _httpRequestDurationMicroseconds: any
  public readonly _numOfRequests: any
  public readonly _numOfErrors: any

  constructor (options: any) {
    this._options = options
    this._httpRequestDurationMicroseconds = new Prometheus.Histogram({
      name: 'http_request_duration_ms',
      help: 'Duration of HTTP requests in ms',
      labelNames: ['method', 'route', 'code'],
      buckets: [0.10, 5, 15, 50, 100, 200, 300, 400, 500]
    })
    this._numOfRequests = new Prometheus.Counter({
      name: 'numOfRequests',
      help: 'Number of requests made to a route',
      labelNames: ['route']
    })
    this._numOfErrors = new Prometheus.Counter({
      name: 'numOfErrors',
      help: 'Number of errors',
      labelNames: ['error']
    })
    // TODO: config: ignore routes, disable metrics
  }

  public start (req: express.Request, res: express.Response, next: express.NextFunction): void {
    res.locals.startEpoch = Date.now()
    res.on('finish', () => {
      if (req.originalUrl !== '/_metrics' && req.originalUrl !== './favicon.ico') {
        const responseTimeInMs = Date.now() - res.locals.startEpoch
        this._httpRequestDurationMicroseconds
          .labels(req.method, req.originalUrl, res.statusCode.toString())
          .observe(responseTimeInMs)
        this._numOfRequests.inc({ route: req.originalUrl })
        if (res.statusCode >= 400) {
          this._numOfErrors.inc({ error: res.statusCode })
        }
      }
    })
    next()
  }

  public endpoint (req: express.Request, res: express.Response): void {
    res.set('Content-Type', Prometheus.register.contentType)
    res.end(Prometheus.register.metrics())
  }
}

export default Metrics