import time
from threading import Event, Thread
import numpy as np
from kamzik3.constants import *
from kamzik3.devices.device import Device
from kamzik3.snippets.snippetsDecorators import expose_method


class DeviceGrabber(Device):

    def __init__(self, device_id=None, config=None):
        self.stopped = Event()
        self.frame_delay = 0
        Device.__init__(self, device_id, config)
        self.connect()

    def _init_attributes(self):
        Device._init_attributes(self)
        npa = np.zeros(dtype=np.uint8, shape=(1, 1, 3))
        self.create_attribute(ATTR_FRAME, group="Grabber", default_value=npa, default_type=TYPE_ARRAY,
                              unit="", readonly=True, display=IMAGE, min_broadcast_timeout=100)
        self.create_attribute(ATTR_MAX_BROADCAST_RATE, default_value=10, default_type=np.uint8, unit="Hz", min_value=0,
                              max_value=10000, set_function=self.set_max_broadcast_rate)
        self.create_attribute(ATTR_FRAMERATE, default_value=10, default_type=np.float, unit="FPS", min_value=1,
                              max_value=10000, set_function=self.set_framerate, decimals=2)
        self.create_attribute(ATTR_FRAMES_GRABBED, default_value=0, default_type=np.uint, readonly=True)

    @expose_method()
    def acquire(self):
        if self.get_value(ATTR_STATUS) == STATUS_BUSY:
            return
        Thread(target=self._acquire_loop).start()

    def _acquire_loop(self):
        """
        self.stopped.clear()
        self.frame_delay = 1. / self.get_value(ATTR_FRAMERATE)
        self.set_status(STATUS_BUSY)

        fps_counter_reference = time_reference = time.perf_counter_ns()
        grabbed_frames_count = 0
        fps_counter = 0
        while not self.stopped.wait((self.frame_delay - (time.perf_counter_ns() - time_reference)) * 1e-9):
            time_reference = time.perf_counter_ns()
            grab_frame_method
            grabbed_frames_count += 1
            fps_counter += 1
            if ret:
                self.set_value(["Grabber", "Frame"], cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB))

            if (time.perf_counter_ns() - fps_counter_reference) >= 1e9:
                self.set_raw_value(ATTR_FRAMERATE, fps_counter)
                self.set_raw_value(ATTR_FRAMES_GRABBED, grabbed_frames_count)
                fps_counter = 0
                fps_counter_reference = time.perf_counter_ns()
        """
        raise NotImplemented

    def set_max_broadcast_rate(self, value):
        self[ATTR_OUTPUT][ATTR_FRAME][ALLOW_BROADCAST] = value > 0
        if value > 0:
            self[ATTR_OUTPUT][ATTR_FRAME].min_broadcast_timeout = (1e9 / value) * 0.95

    def set_framerate(self, value):
        self.frame_delay = 1e9 / value

    def handle_configuration(self):
        start_at = time.time()
        self._config_attributes()
        self.set_status(STATUS_CONFIGURED)
        self.logger.info(u"Device configuration took {} sec.".format(time.time() - start_at))

    @expose_method()
    def stop(self):
        self.stopped.set()
        self.set_status(STATUS_IDLE)

    def close(self):
        self.stop()
        Device.close(self)
