import cv2
import json
import logging
import zbarlight

from PIL import Image
from requests.exceptions import HTTPError

from owltail.api_handler import APIHandler
from owltail.core.const import STOP_SESSION, PLAYLIST_FINISHED
from owltail.ws_server import WebSocketMixin


default_api_handler = APIHandler()
logger = logging.getLogger(__name__)


class QRCodeReader(WebSocketMixin):
    def __init__(self, api_handler=default_api_handler):
        super().__init__()
        self.api_handler = api_handler
        self.open_cam()

    def open_cam(self):
        self.video_capture = cv2.VideoCapture(0)

    def read_cam(self):
        rval, frame = self.video_capture.read()
        if frame:
            pil_img = Image.fromarray(frame)
            return zbarlight.scan_codes('qrcode', pil_img)

    def close_cam(self):
        self.video_capture.release()

    def _check_validity(self, code):
        '''
        Check with the owlright API the validity of the code
        '''
        try:
            response = self.api_handler.check_qrcode_validity(code)
        except HTTPError:
            return {'code_valid': False}
        return response

    def _listen_ws(self):
        return json.loads(self.ws.recv())

    def filter_ws_listening(self):
        while True:
            message = self._listen_ws()
            if message in [STOP_SESSION, PLAYLIST_FINISHED]:
                return message

    def code_treatment(self, code):
        self._send_ws_message_keep_open({'operationId': 'QR_CODE_READING'})
        json = {'operationId': 'QR_CODE_CHECKED'}
        response = self._check_validity(code)
        json.update(response)
        self._send_ws_message_keep_open(json)
        return response['code_valid']

    def run(self):
        while True:
            code = self.read_cam()
            if code:
                print(code)
                self.close_cam()
                valide = self.code_treatment(code[0].decode('utf8'))
                if valide:
                    self._listen_ws()
                self.open_cam()


if __name__ == "__main__":
    reader = QRCodeReader()
    try:
        reader.run()
    except KeyboardInterrupt:
        reader.close_cam()
