import cv2
import numpy as np
import time


class CaptureManager(object):
    def __init__(self, capture, preview_window_manager=None, should_mirror_preview = False):

        self.preview_window_manager = preview_window_manager
        self.should_mirror_preview = should_mirror_preview

        self._capture = capture
        self._channel = 0
        self._entered_frame = False
        self._frame = None
        self._frames_elapsed = long(0)
        self._fps_est = None

    @property
    def channel(self):
        return self._channel

    @channel.setter
    def channel(self):
        return self._channel

    @property
    def frame(self):
        if self._entered_frame and self._frame is None:
            _, self._frame = self._capture.retrieve(channel=self.channel)
        return self._frame

    def enter_frame(self):
        # capture the next frame

        assert not self._entered_frame, 'previous enter_frame() had no matching exit_frame()'
        if self._capture is not None:
            self._entered_frame = self._capture.grab()

    def exit_frame(self):
        # draw to window, write to files, release the frame

        # frame is retrievable or not
        if self.frame is None:
            self._entered_frame = False
            return

        if self._frames_elapsed == 0:
            self._start_time = time.time()
        else:
            time_elapsed = time.time() - self._start_time
            self._fps_est = self._frames_elapsed / time_elapsed
        self._frames_elapsed += 1

        # draw
        if self.preview_window_manager is not None:
            if self.should_mirror_preview:
                mirrored_frame = np.fliplr(self._frame).copy()
                self.preview_window_manager.show(mirrored_frame)
            else:
                self.preview_window_manager.show(self._frame)

        # release the frame
        self._frame = None
        self._entered_frame = False



class WindowManager(object):

    def __init__(self, window_name, keypress_callback = None):
        self.keypress_callback = keypress_callback
        self._window_name = window_name
        self._is_window_created = False

    @property
    def is_window_created(self):
        return self._is_window_created

    def create_window(self):
        cv2.namedWindow(self._window_name)
        self._is_window_created = True

    def show(self, frame):
        cv2.imshow(self._window_name, frame)

    def destroy_window(self):
        cv2.destroyWindow(self._window_name)
        self._is_window_created = False

    def process_events(self):
        keykode = cv2.waitKey(1)
        if self.keypress_callback is not None and keykode != -1:
            keykode &= 0xFF
            self.keypress_callback(keykode)

[((81, 8, 81, 42), 'cv2.namedWindow', 'cv2.namedWindow', ({(81, 24, 81, 41): 'self._window_name'}, {}), '(self._window_name)', False, 'import cv2\n'), ((85, 8, 85, 44), 'cv2.imshow', 'cv2.imshow', ({(85, 19, 85, 36): 'self._window_name', (85, 38, 85, 43): 'frame'}, {}), '(self._window_name, frame)', False, 'import cv2\n'), ((88, 8, 88, 44), 'cv2.destroyWindow', 'cv2.destroyWindow', ({(88, 26, 88, 43): 'self._window_name'}, {}), '(self._window_name)', False, 'import cv2\n'), ((92, 18, 92, 32), 'cv2.waitKey', 'cv2.waitKey', ({(92, 30, 92, 31): '1'}, {}), '(1)', False, 'import cv2\n'), ((49, 31, 49, 42), 'time.time', 'time.time', ({}, {}), '()', False, 'import time\n'), ((51, 27, 51, 38), 'time.time', 'time.time', ({}, {}), '()', False, 'import time\n'), ((58, 33, 58, 55), 'numpy.fliplr', 'np.fliplr', ({(58, 43, 58, 54): 'self._frame'}, {}), '(self._frame)', True, 'import numpy as np\n')]