from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import threading


class ThreadInterface(threading.Thread):
    """
    Provides a common thread interface which executes a provided function
    continuously until a pause or shutdown request is received. If paused, the
    provided function can be ran once then resume pause with the `spin_once`
    function.
    """
    def __init__(self):
        super(ThreadInterface, self).__init__()
        self.daemon = True
        self._shutdown_event = threading.Event()
        self._pause_event = threading.Event()
        self._spin_once = False

    def run(self):
        while not self.shutdown:
            while not (self.pause or self.shutdown):
                try:
                    self._run_impl()
                except Exception as err:
                    pass
                if self._spin_once:
                    self.pause = True
                    self._spin_once = False

    @property
    def shutdown(self):
        return self._shutdown_event.is_set()

    @shutdown.setter
    def shutdown(self, val):
        assert isinstance(val, bool)
        if val:
            self._shutdown_event.set()
        else:
            self._shutdown_event.clear()

    @property
    def pause(self):
        return self._pause_event.is_set()

    @pause.setter
    def pause(self, val):
        assert isinstance(val, bool)
        if val:
            self._pause_event.set()
        else:
            self._pause_event.clear()

    def spin_once(self):
        if self.shutdown:
            raise ValueError('Cannot spin once after shutdown!')
        self.pause = True
        self._spin_once = True
        self.pause = False

    def _run_impl(self):
        raise NotImplementedError
