# Copyright 3D Control Systems, Inc. All Rights Reserved 2017-2019.
# Built in San Francisco.

# This software is distributed under a commercial license for personal,
# educational, corporate or any other use.
# The software as a whole or any parts of it is prohibited for distribution or
# use without obtaining a license from 3D Control Systems, Inc.

# All software licenses are subject to the 3DPrinterOS terms of use
# (available at https://www.3dprinteros.com/terms-and-conditions/),
# and privacy policy (available at https://www.3dprinteros.com/privacy-policy/)

import sys
import time
import logging

from io import BytesIO

import config
import http_client
import log
from dual_cam import Camera


class M5thCamera(Camera):
    def __init__(self, parent):
        self.logger = logging.getLogger(__name__)
        self.stop_flag = False
        self.parent = parent
        self.ip = parent.ip
        self.http_client = None
        self.cloud_camera_number = None
        self.init_settings()
        self.init_parameters()
        self.init()
        self.init_user_token()

    def init_user_token(self):
        self.http_client = http_client.HTTPClient(self, keep_connection_flag=True, logging_level=logging.WARNING)
        self.token = config.get_app().user_login.user_token

    def init(self):
        Camera.init(self)
        self.min_loop_time = 1

    @log.log_exception
    def main_loop(self):
        self.init_parameters()
        self.resized.append(True)
        self.fails.append(0)
        if not self.ip:
            self.logger.error('No IP. Stopping...')
            return
        self.makerbot = self.parent.makerbot
        self.cloud_camera_number = self.get_number_by_ip()
        time.sleep(self.min_loop_time)
        while not self.stop_flag and not self.parent.stop_flag:
            self.logger.debug("camera %s cycle" % self.cloud_camera_number)
            frame_start_time = time.monotonic()
            frame = self.make_shot()
            if frame:
                # self.logger.debug("Got frame from camera N" + str(number))
                self.send_frame(frame)
            else:
                self.logger.warning("No frame from camera N" + str(self.cloud_camera_number))
            while time.monotonic() < frame_start_time + 0.001 + self.min_loop_time:
                time.sleep(0.01)
        self.http_client.close()
        sys.exit(0)

    def get_number_by_ip(self):
        numbers = [i.zfill(3) for i in self.ip.split(".")]
        try:
            number = int(''.join(numbers))
        except ValueError:
            number = 0
        return number

    def get_camera_number_for_cloud(self):
        return self.cloud_camera_number

    def make_shot(self):
        if self.is_same_image_frame():
            return self.SAME_IMAGE
        try:
            _, width, height, t, image_data = self.makerbot._get_raw_camera_image_data()
        except Exception as e:
            self.logger.error("Error in makerbot 5th gen camera: " + str(e))
        else:
            if not image_data:
                self.logger.warning('Failed to get camera frame: %i, %i' % (width, height))
                return None
            if t == 1:
                bgr_rows = self.makerbot.yuv_to_bgr_rows(BytesIO(image_data), width, height)
                frame = self.np.array(bgr_rows).reshape(height, width, 3)
                return self.get_image_from_cv2_frame(self.resize_cv2_frame(frame))
            elif t == 2:
                return self.resize_image(image_data)
            self.logger.warning('Failed to get camera frame (wrong type): %i, %i, %i' % (width, height, t))
