#!/usr/bin/env python

import cv2
import logging
import zbarlight

from json import loads
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()
        self._create_ws_connection()

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

    def read_cam(self):
        rval, frame = self.video_capture.read()
        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 {'codeValid': False}
        return response

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

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

    def code_treatment(self, code):
        self._send_websocket_message({'operationId': 'QR_CODE_READING'})
        message = {'operationId': 'QR_CODE_CHECKED'}
        json_response = self._check_validity(code)
        message['codeValid'] = json_response['codeValid']
        message['data'] = json_response
        self._send_websocket_message(message)
        return (
            message['data']['codeValid'] and
            message['data']['remainingTime'] > 0
        )

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