#!/usr/bin/env ruby
# frozen_string_literal: true

require 'optparse'
require 'json'
require 'logger'

require_relative "./../lib/prometheus_exporter"
require_relative "./../lib/prometheus_exporter/server"

def run
  options = {
    logger_path: STDERR
  }
  custom_collector_filename = nil
  custom_type_collectors_filenames = []

  OptionParser.new do |opt|
    opt.banner = "Usage: prometheus_exporter [options]"
    opt.on('-p',
           '--port INTEGER',
           Integer,
           "Port exporter should listen on (default: #{PrometheusExporter::DEFAULT_PORT})") do |o|
      options[:port] = o.to_i
    end
    opt.on('-b',
           '--bind STRING',
           String,
           "IP address exporter should listen on (default: #{PrometheusExporter::DEFAULT_BIND_ADDRESS})") do |o|
      options[:bind] = o.to_s
    end
    opt.on('-t',
           '--timeout INTEGER',
           Integer,
           "Timeout in seconds for metrics endpoint (default: #{PrometheusExporter::DEFAULT_TIMEOUT})") do |o|
      options[:timeout] = o.to_i
    end
    opt.on('--prefix METRIC_PREFIX', "Prefix to apply to all metrics (default: #{PrometheusExporter::DEFAULT_PREFIX})") do |o|
      options[:prefix] = o.to_s
    end
    opt.on('--label METRIC_LABEL', "Label to apply to all metrics (default: #{PrometheusExporter::DEFAULT_LABEL})") do |o|
      options[:label] = JSON.parse(o.to_s)
    end
    opt.on('-c', '--collector FILE', String, "(optional) Custom collector to run") do |o|
      custom_collector_filename = o.to_s
    end
    opt.on('-a', '--type-collector FILE', String, "(optional) Custom type collectors to run in main collector") do |o|
      custom_type_collectors_filenames << o
    end
    opt.on('-v', '--verbose') do |o|
      options[:verbose] = true
    end
    opt.on('-g', '--histogram', "Use histogram instead of summary for aggregations") do |o|
      options[:histogram] = true
    end
    opt.on('--auth FILE', String, "(optional) enable basic authentication using a htpasswd FILE") do |o|
      options[:auth] = o
    end
    opt.on('--realm REALM', String, "(optional) Use REALM for basic authentication (default: \"#{PrometheusExporter::DEFAULT_REALM}\")") do |o|
      options[:realm] = o
    end

    opt.on('--unicorn-listen-address ADDRESS', String, '(optional) Address where unicorn listens on (unix or TCP address)') do |o|
      options[:unicorn_listen_address] = o
    end

    opt.on('--unicorn-master PID_FILE', String, '(optional) PID file of unicorn master process to monitor unicorn') do |o|
      options[:unicorn_pid_file] = o
    end

    opt.on('--logger-path PATH', String, '(optional) Path to file for logger output. Defaults to STDERR') do |o|
      options[:logger_path] = o
    end
  end.parse!

  logger = Logger.new(options[:logger_path])
  logger.level = Logger::WARN

  if options.has_key?(:realm) && !options.has_key?(:auth)
    logger.warn "Providing REALM without AUTH has no effect"
  end

  if options.has_key?(:auth)
    unless File.exist?(options[:auth]) && File.readable?(options[:auth])
      logger.fatal "The AUTH file either doesn't exist or we don't have access to it"
      exit 1
    end
  end

  if custom_collector_filename
    require File.expand_path(custom_collector_filename)
    found = false

    base_klass = PrometheusExporter::Server::CollectorBase

    ObjectSpace.each_object(Class) do |klass|
      if klass < base_klass && klass != base_klass
        options[:collector_class] = klass
        found = true
      end
    end

    if !found
      logger.fatal "Can not find a class inheriting off PrometheusExporter::Server::CollectorBase"
      exit 1
    end
  end

  if custom_type_collectors_filenames.length > 0
    custom_type_collectors_filenames.each do |t|
      require File.expand_path(t)
    end

    ObjectSpace.each_object(Class) do |klass|
      if klass < PrometheusExporter::Server::TypeCollector
        options[:type_collectors] ||= []
        options[:type_collectors] << klass
      end
    end
  end

  runner = PrometheusExporter::Server::Runner.new(options)

  puts "#{Time.now} Starting prometheus exporter on #{runner.bind}:#{runner.port}"
  runner.start
  sleep
end

run