import ctypes
import struct
from ctypes import *
import sys

from PyQt5.QtCore import pyqtSignal, QMutex

from components.component import Component

from hikrobot_dll import *

class HikrobotSmartCamera(Component):

    def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True, num_cameras=1):
        super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
        self.lock = QMutex()
        self.simulate = "--sim-camera" in sys.argv
        self.num_cameras=num_cameras
        self.lib=mv_lib

    def config_changed(self):
        self.lib.MV_VS_DEVICE_INFO_LIST()
        for cam_idx in range(self.num_cameras):
            pass

    @Component.reconfig_on_error
    def _get(self):
        frame = None
        super()._get([frame])

    def GetFrame(self,handle):
        nRet = MV_VS_OK
        stFrameData = MV_VS_DATA()
        while True:
            nRet = self.lib.MV_VS_GetResultData(handle, ctypes.byref(stFrameData), 1000)
            if nRet == MV_VS_OK:
                # Print frame information
                print(f"Frame Width: [{stFrameData.nImageWidth}], Height: [{stFrameData.nImageHeight}], ImageLen: [{stFrameData.nImageLen}]")

                # Process chunk data
                currentDataTag = 0
                while stFrameData.nChunkDataLen > currentDataTag:
                    chunkLength = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 4 - currentDataTag)[0]
                    chunkID = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - currentDataTag)[0]

                    print(f"chunkLength [{chunkLength}], chunkID: [{chunkID}]")

                    if chunkLength <= 0 or chunkLength > stFrameData.nChunkDataLen - 8 - currentDataTag:
                        # Handle exception
                        break

                    if chunkID == CHUNK_RESULT_PORT:  # Result data in JSON format
                        chResultInfo = ctypes.cast(stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag), ctypes.POINTER(ctypes.c_char))
                        print(f"chResultInfo [{chResultInfo.value.decode()}] end")

                    elif chunkID == CHUNK_MASK_IMAGE_PORT:  # Mask image data
                        maskModID = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag)[0]
                        maskModFormat = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 4)[0]
                        maskModWidth = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 8)[0]
                        maskModHeight = struct.unpack_from("<I", stFrameData.pChunkData, stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 12)[0]

                        print(f"Mask ModID[{maskModID}], ModFormat[{maskModFormat}], ModWidth[{maskModWidth}], ModHeight[{maskModHeight}], ")

                        chMaskModImageData = ctypes.cast(stFrameData.pChunkData + (stFrameData.nChunkDataLen - 8 - chunkLength - currentDataTag + 16), ctypes.POINTER(ctypes.c_char))
                        print(f"Mask data length [{chunkLength - 16}]")

                    currentDataTag += 8 + chunkLength

                # Release frame buffer
                nRet = self.lib.MV_VS_ReleaseResultData(handle, ctypes.byref(stFrameData))
                if nRet != MV_VS_OK:
                    print(f"Release frame buffer fail! nRet [0x{nRet:x}]")
            else:
                print(f"Get frame buffer fail! nRet [0x{nRet:x}]")
