# -*- coding: utf-8 -*-

# Copyright (C) 2015-2018 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

from builtins import object
import logging
import threading

from kombu import Queue
from kombu.mixins import ConsumerMixin
from xivo_bus.resources.ipbx.event import ReloadIpbxEvent

logger = logging.getLogger(__name__)


class Worker(ConsumerMixin):

    def __init__(self, connection, exchange, msg_handler):
        self.connection = connection
        self._exchange = exchange
        self._msg_handler = msg_handler

    def get_consumers(self, Consumer, channel):
        queues = [Queue(exchange=self._exchange, routing_key=routing_key, exclusive=True)
                  for routing_key in self._msg_handler.routing_keys()]
        return [Consumer(queues=queues, callbacks=[self._on_message])]

    def _on_message(self, body, message):
        message.ack()
        try:
            self._msg_handler.handle_msg(body)
        except Exception:
            logger.warning('Unexpected error while handling AMQP message', exc_info=True)


class AMQPInterface(object):

    def __init__(self, connection, service_proxy, bus_exchange):
        self._thread = None
        self._exchange = bus_exchange
        self._worker = self._new_worker(connection, service_proxy)

    def _new_worker(self, connection, service_proxy):
        msg_handler = _MessageHandler([
            _ReloadIpbxEvent(service_proxy),
        ])
        return Worker(connection, self._exchange, msg_handler)

    def start(self):
        self._thread = threading.Thread(target=self._run)
        self._thread.start()

    def stop(self):
        if self._thread is None:
            return

        self._worker.should_stop = True
        self._thread.join()
        self._thread = None

    def _run(self):
        self._worker.run()


class _MessageHandler(object):

    def __init__(self, event_handlers):
        self._event_handlers = dict((event_handler.Event.name, event_handler)
                                    for event_handler in event_handlers)

    def routing_keys(self):
        return [event_handler.Event.routing_key for event_handler in self._event_handlers.values()]

    def handle_msg(self, decoded_msg):
        event_name = decoded_msg['name']
        self._event_handlers[event_name].handle_event(decoded_msg)


class _BaseEventHandler(object):

    def __init__(self, service_proxy):
        self._service_proxy = service_proxy


class _ReloadIpbxEvent(_BaseEventHandler):

    Event = ReloadIpbxEvent

    def handle_event(self, decoded_msg):
        self._service_proxy.on_ipbx_reload(decoded_msg['data']['commands'])
