require 'amqp'
require 'jam_ruby'
require 'bugsnag'

# Creates a connection to RabbitMQ.
# On that single connection, a channel is created (which is a way to multiplex multiple queues/topics over the same TCP connection with rabbitmq)
# Then connections to the client_exchange and user_exchange are made, and put into the MQRouter static variables
# If this code completes (which implies that Rails can start to begin with, because this is in an initializer),
# then the Rails app itself is free to send messages over these exchanges
# TODO: reconnect logic if rabbitmq goes down...

module JamWebEventMachine

  def self.run_em

      EventMachine.error_handler{|e|
        Bugsnag.notify(e)
      }

      EM.run do
        # this is global because we need to check elsewhere if we are currently connected to amqp before signalling success with some APIs, such as 'create session'
        $amqp_connection_manager = AmqpConnectionManager.new(true, 4, :host => Rails.application.config.rabbitmq_host, :port => Rails.application.config.rabbitmq_port)
        $amqp_connection_manager.connect do |channel|

            AMQP::Exchange.new(channel, :topic, "clients") do |exchange|
              Rails.logger.debug("#{exchange.name} is ready to go")
              MQRouter.client_exchange = exchange
            end

            AMQP::Exchange.new(channel, :topic, "users") do |exchange|
              Rails.logger.debug("#{exchange.name} is ready to go")
              MQRouter.user_exchange = exchange
              Rails.logger.debug "MQRouter.user_exchange = #{MQRouter.user_exchange}"
            end
        end
      end
  end

  def self.die_gracefully_on_signal
    Rails.logger.debug("*** die_gracefully_on_signal")
    Signal.trap("INT")  { EM.stop }
    Signal.trap("TERM") { EM.stop }
  end

  def self.start
    if defined?(PhusionPassenger) 
      Rails.logger.debug("PhusionPassenger detected")

      PhusionPassenger.on_event(:starting_worker_process) do |forked|
      # for passenger, we need to avoid orphaned threads
        if forked && EM.reactor_running?
	  Rails.logger.debug("stopping EventMachine")
          EM.stop
        end
	Rails.logger.debug("starting EventMachine")
        Thread.new {
	  run_em
        }
        die_gracefully_on_signal
      end
    elsif defined?(Unicorn)
      Rails.logger.debug("Unicorn detected--do nothing at initializer phase")
    else
      Rails.logger.debug("Development environment detected")
      Thread.abort_on_exception = true

      # create a new thread separate from the Rails main thread that EventMachine can run on
      Thread.new do
        run_em
      end
    end
  end
end

JamWebEventMachine.start
