import zmq
from abc import ABCMeta, abstractmethod
from threading import Thread


class WorkerThread(object):
    __meta__ = ABCMeta

    def __init__(self, context, worker_address, idle_timeout):
        self.context = context
        self.worker_address = worker_address
        self.idle_timeout = idle_timeout

        self.is_working = False
        self.is_idle = False

        self.running = False
        self.inactive_time = 0
        self.thread = None

    def start(self):
        if self.running:
            return

        self.running = True
        self.inactive_time = 0

        self.thread = Thread(target=self.run)
        self.thread.daemon = True
        self.thread.start()

    def stop(self):
        self.running = False

    def join(self):
        self.thread.join()

    def run(self):
        pull_socket = self.create_socket(self.worker_address)

        while self.running:
            ready = pull_socket.poll(1000, zmq.POLLIN)
            if ready & zmq.POLLIN == 0:
                self.is_working = False
                self.inactive_time += 1000
                if self.inactive_time > self.idle_timeout:
                    self.is_idle = True

                continue

            self.inactive_time = 0
            self.is_idle = False
            self.is_working = True

            data = pull_socket.recv()
            self.do_work(data)

    @abstractmethod
    def do_work(self, data):
        # type: (str) -> None
        raise NotImplementedError()

    @abstractmethod
    def dispose(self):
        raise NotImplementedError()

    @abstractmethod
    def create_socket(self, address):
        raise NotImplementedError()
