import zmq
import time
import logging

from zmq.eventloop.zmqstream import ZMQStream
from server import config
from .common import context

from server.svc_pb2 import Packet, SERVICE, MONITOR

_svc_cmd_handler = None
_mon_cmd_handler = None


class CReceiver(object):
    def __init__(self, port):
        self._port = port

        self._url = 'tcp://*:{port}'.format(port=self._port)
        self._socket = None
        self._stream = None

    def setup(self):
        try:
            self._socket = context.socket(zmq.PULL)
            self._socket.bind(self._url)

            self._stream = ZMQStream(self._socket)
            self._stream.on_recv(lambda future_msg: self.handle_recv(future_msg))

            time.sleep(1)
        except Exception as e:
            logging.error("Can't bind receiver socket on port {port}: {exception}".format(port=self._port, exception=e))

    def handle_recv(self, future_msg):
        pkt = None

        try:
            buf = future_msg.result()
            pkt = Packet()
            pkt.ParseFromString(buf[0])
        except Exception as e:
            logging.error("handle_recv error: {exception}".format(exception=e))
            return

        client_type = pkt.client_type
        if client_type == SERVICE:
            if _svc_cmd_handler is not None:
                _svc_cmd_handler(pkt)
        elif client_type == MONITOR:
            if _mon_cmd_handler is not None:
                _mon_cmd_handler(pkt)


_receiver = CReceiver(config.instance.get_pull_port())


def setup(svc_handler=None, mon_handler=None):
    global _receiver
    global _svc_cmd_handler
    global _mon_cmd_handler

    _svc_cmd_handler = svc_handler
    _mon_cmd_handler = mon_handler
    _receiver.setup()
