#!/usr/bin/env ruby

require 'bunny'
require 'logger'
require 'yaml'

$0 = 'onapp_mq_tracer'

module OnApp
  module Utilities
    module MQ
      module Tracer
        extend self

        EXCHANGE_NAME  = "amq.rabbitmq.trace".freeze
        CONFIG_FILE    = "/onapp/utilities/mq-tracer/config.yml".freeze
        TRACE_LOG_FILE = "/onapp/utilities/mq-tracer/trace.log".freeze
        UTIL_LOG_FILE  = "/onapp/utilities/mq-tracer/util.log".freeze

        LOW    = [1, 2, 3].freeze
        MEDIUM = [2, 3].freeze
        HIGH   = [3].freeze

        def perform
          # Connect to MQ server
          connection = Bunny.new(host: config['rabbitmq_host'],
                                 port: config['rabbitmq_port'],
                                vhost: config['rabbitmq_vhost'],
                                 user: config['rabbitmq_login'],
                                 pass: config['rabbitmq_password'])
          begin
            connection.start
          rescue Bunny::TCPConnectionFailed => e
            util_logger.debug("MQ connection failed: #{e.message}") and raise
          end

          util_logger.debug("MQ connection established")

          # Consumes messages from debug queue
          channel  = connection.create_channel
          exchange = channel.topic(EXCHANGE_NAME, durable: true,
                                              auto_delete: false,
                                                 internal: true)
          queue    = channel.queue(durable: false, auto_delete: true)
          queue.bind(exchange, routing_key: '#')

          # If service stopped
          Signal.trap("TERM") do
            channel.close
            connection.close
            util_logger.debug("MQ connection terminated")
          end

          ## Subscribe for all messages form trace
          queue.subscribe(block: true) do |body, properties, delivery_info|
            ## Logs info into given or some default file
            log_body          = verbosity_level?(LOW)    ? body          : ''
            log_properties    = verbosity_level?(MEDIUM) ? properties    : ''
            log_delivery_info = verbosity_level?(HIGH)   ? delivery_info : ''

            trace_logger.debug("#{log_body} #{log_properties} #{log_delivery_info}")
          end
        end

        private

        def trace_logger
          Logger.new(TRACE_LOG_FILE)
        end

        def util_logger
          Logger.new(UTIL_LOG_FILE)
        end

        def config
          unless File.exists?(CONFIG_FILE)
            util_logger.debug("Config file doesn't exists!")

            raise "Config file doesn't exists!"
          end

          unless File.readable?(CONFIG_FILE)
            util_logger.debug("Config file doesn't exists!")

            raise "Config file doesn't exists!"
          end

          YAML.load_file(CONFIG_FILE)
        end

        def verbosity_level?(levels)
          log_level = [(config['log_verbosity_level'] || 1).to_i, 3].min
          levels.include?(log_level)
        end
      end
    end
  end
end

OnApp::Utilities::MQ::Tracer.perform
