#!D:/IDE/anaconda3/envs python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName：Request.py\n
 @DateTime: 2025/6/26 17:15\n
 @Author  ：xsh
"""
import datetime
import sys
from PyQt5                              import Qt
from AppInterfaces.ModelInterface       import RequestModelInterface
from AppCore.Levels                     import *
from AppUtils.utils                     import *
from AppCore.Requests                   import *
from AppSettings.Settings               import *
import numpy as np
from AppCore.AppRequestModels.CameraRequest import CameraRequest
from AppUtils.ImageUtils import ImageUtils



class Request(RequestModelInterface):
    code        : int
    data        : dict
    message     : str
    callback    : str
    level       : int
    Handler     : object
    Buffer      : object
    __slots__ = (
        'code'    ,
        'data'    ,
        'message' ,
        'callback',
        'level'   ,
        'Handler' ,
        'Buffer'  ,
    )
    __types__ = (
        int       ,
        dict      ,
        str       ,
        str       ,
        int       ,
        object    ,
        object    ,

    )
    def __init__(self, **args):
        super(Request, self).__init__()
        self.initialize()
        self.initParameter(**args)

    @classmethod
    def instance(cls, buffer, **args) -> "Request":
        result: Request = cls.__new__(cls)
        result.__init__()
        result.asObject(buffer)
        if isinstance(args, dict):
            result.initParameter(**args)
        return result

    @classmethod
    def NoneWebAPI(cls, handle = None, **args) -> 'Request':
        result: Request = cls.__new__(cls)
        result.__init__()
        if isinstance(args, dict):
            result.initParameter(**args)
        result.level = WebAPILevel.NoneWebAPI
        result.callback = WebAPILevel.toString(WebAPILevel.NoneWebAPI)
        result.Handler = handle
        return result

    def initParameter(self, **args):
        if not isinstance(args, dict):
            return
        self.code       = AppConvert.ObjectConvert(args.get('code', CODE_SUCCESS), int)
        self.data       = AppConvert.ObjectConvert(args.get('data', {}), dict)
        self.message    = AppConvert.ObjectConvert(args.get('message', ""), str)
        self.callback   = AppConvert.ObjectConvert(args.get('callback', ""), str)
        self.level      = AppConvert.ObjectConvert(args.get('level', -1), int)
        self.Handler    = args.get('Handler', None)
        self.Buffer     = args.get('Buffer', None)

    def initValue(self):
        super(Request, self).initValue()
        self.code       = CODE_SUCCESS
        self.data       = {}
        self.message    = ""
        self.callback   = ""
        self.level      = -1
        self.Handler    = None
        self.Buffer     = None

    def toJson(self) -> str:
        return ConvertUtils.toJson({
            'code'      : self.code         ,
            'data'      : self.data         ,
            'message'   : self.message      ,
            'callback'  : self.callback     ,
            'level'     : self.level        ,
        })

    def asJson(self, buffer: str):
        self.deserialize(ConvertUtils.asJson(buffer))

    def toYaml(self) -> str:
        return ConvertUtils.toYaml({
            'code'      : self.code     ,
            'data'      : self.data     ,
            'message'   : self.message  ,
            'callback'  : self.callback ,
            'level'     : self.level    ,
        })

    def asYaml(self, buffer: str):
        self.deserialize(ConvertUtils.asYaml(buffer))

    def serialize(self) -> dict[str, object]:
        return {
            'code'      : self.code     ,
            'data'      : self.data     ,
            'message'   : self.message  ,
            'callback'  : self.callback ,
            'level'     : self.level    ,
            'Handler'   : self.Handler  ,
            'Buffer'    : self.Buffer   ,
        }

    def deserialize(self, buffer: dict[str, object]):
        if isinstance(buffer, RequestModelInterface):
            self.data = buffer.serialize()
        elif isinstance(buffer, Request):
            if id(buffer) != id(self):
                self.initParameter(**buffer.serialize())
        elif isinstance(buffer, dict):
            if 'data' in buffer.keys() and 'callback' in buffer.keys() :
                for _property, value in buffer.items():
                    setattr(self, _property, value)
            else:
                self.data = buffer
        elif isinstance(buffer, str):
            _buffer = AppConvert.asJson(buffer)
            if isinstance(buffer, dict):
                for _property, value in buffer.items():
                    if _property in self.__slots__:
                        setattr(self, _property, value)
                    else:
                        setattr(self, _property, value)


    def asObject(self, other):

        if isinstance(other, Request):
            if id(other) != id(self):
                self.deserialize(other.serialize())
        elif isinstance(other, RequestModelInterface):
            self.deserialize(other.serialize())
        elif isinstance(other, dict):
            self.deserialize(other)

    def toObject(self, other):
        if isinstance(other, RequestModelInterface):
            if id(self) != id(other):
                other.deserialize(self.serialize())
        elif isinstance(other, Request):
            if id(other) != id(self):
                other.deserialize(self.serialize())
        elif isinstance(other, dict):
            other.update(self.serialize())



    def reload(self) -> bool:
        isLoad: bool = self.load()
        if not isLoad:
            isLoad = self.save()
        return isLoad


    def save(self) -> bool:
        return AppUtils.save_string_to_file(self.save_filename(), self.toYaml())


    def load(self) -> bool:
        buffer: str = AppUtils.read_string_from_file(self.save_filename())
        if AppUtils.isEmpty(buffer):
            return False
        try:
            self.asYaml(buffer)
        except Exception as e:
            return False
        return True
        pass

    def save_filename(self) -> str:
        return AppUtils.toSourceFile(f"Request/{self.Name}.yaml")

    @classmethod
    def FocusingInstance(cls, **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.level = WebAPILevel.focusingPosition
        result.callback = WebAPILevel.toString(result.level)
        result.data = dict(**args)
        return result

    @classmethod
    def EmptyFocusingInstance(cls) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.level = WebAPILevel.focusingPosition
        result.callback = WebAPILevel.toString(result.level)
        result.data = None
        return result

    @classmethod
    def APIInstance(cls, level: int, **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.level = level if level in WebAPILevel.all() else WebAPILevel.NoneWebAPI
        result.callback = WebAPILevel.toString(result.level)
        result.data = dict(**args)
        return result

    @classmethod
    def APIClearPreview(cls, changedSlide: bool = True) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.level = WebAPILevel.clearPreview
        result.callback = WebAPILevel.toString(result.level)
        result.data['changedSlide'] = changedSlide
        return result
    @classmethod
    def SlideAreaImage(cls, buffer: (np.ndarray, str, CameraRequest), **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getSlideAreaImage
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.SlideAreaImage_W
        h: int = AppConfig.sizeConfig.SlideAreaImage_H
        if isinstance(buffer, np.ndarray):
            result.data['base64'] = ImageUtils.image_to_base64(ImageUtils.image_resize(buffer, w, h))
        elif isinstance(buffer, str):
            result.data['base64'] = buffer
        elif isinstance(buffer, CameraRequest):
            result.data['base64'] = buffer.toBase64(w, h)
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result

    @classmethod
    def PreviewImage(cls, buffer: (np.ndarray, str, CameraRequest), **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getPreviewImage
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.PreviewImage_W
        h: int = AppConfig.sizeConfig.PreviewImage_H
        if isinstance(buffer, np.ndarray):
            result.data['base64'] = ImageUtils.image_to_base64(ImageUtils.image_resize(buffer, w, h))
        elif isinstance(buffer, str):
            result.data['base64'] = buffer
        elif isinstance(buffer, CameraRequest):
            result.data['base64'] = buffer.toBase64(w, h)
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result

    @classmethod
    def VideoStream(cls, buffer: (np.ndarray, str, CameraRequest), **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getVideoStream
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.VideoStream_W
        h: int = AppConfig.sizeConfig.VideoStream_H

        if isinstance(buffer, np.ndarray):
            result.data['base64'] = ImageUtils.image_to_base64(
                ImageUtils.image_resize(buffer, w, h))

        elif isinstance(buffer, str):
            result.data['base64'] = buffer
        elif isinstance(buffer, CameraRequest):
            result.data['base64'] = buffer.toBase64(w, h)
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result

    @classmethod
    def MPreviewImage(cls, buffer: (np.ndarray, str, CameraRequest), **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getPreviewImage
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.MPreviewImage_W
        h: int = AppConfig.sizeConfig.MPreviewImage_H
        if isinstance(buffer, np.ndarray):
            result.data['base64'] = ImageUtils.image_to_base64(ImageUtils.image_resize(buffer, w, h))
        elif isinstance(buffer, str):
            result.data['base64'] = buffer
        elif isinstance(buffer, CameraRequest):
            result.data['base64'] = buffer.toBase64(w, h)
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result
    @classmethod
    def MVideoStream(cls, buffer: (np.ndarray, str, CameraRequest), **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getVideoStream
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.MVideoStream_W
        h: int = AppConfig.sizeConfig.MVideoStream_H

        if isinstance(buffer, np.ndarray):
            result.data['base64'] = ImageUtils.image_to_base64(
                ImageUtils.image_resize(buffer, w, h))

        elif isinstance(buffer, str):
            result.data['base64'] = buffer
        elif isinstance(buffer, CameraRequest):
            result.data['base64'] = buffer.toBase64(w, h)
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result

    @classmethod
    def ImageList(cls, buffer: list[np.ndarray], **args) -> 'Request':
        result: cls = cls.__new__(cls)
        result.__init__()
        result.code = CODE_SUCCESS
        result.level = WebAPILevel.getImageList
        result.callback = WebAPILevel.toString(result.level)
        from AppSettings.AppSetting import AppConfig
        w: int = AppConfig.sizeConfig.ImageList_W
        h: int = AppConfig.sizeConfig.ImageList_H
        array: list[str] = []
        if isinstance(buffer, list):
            for image in buffer:
                array.append(ImageUtils.image_to_base64(ImageUtils.image_resize(image, w, h)))
        result.data['base64'] = array
        for _property, value in args.items():
            if AppConvert.isBase(value) and _property != 'base64':
                result.data[_property] = value
        return result








    @property
    def has_code        (self) -> bool: return hasattr(self, 'code'    ) and self.code         is not None

    @property
    def has_data        (self) -> bool: return hasattr(self, 'data'    ) and self.data         is not None

    @property
    def has_message     (self) -> bool: return hasattr(self, 'message' ) and self.message      is not None

    @property
    def has_callback    (self) -> bool: return hasattr(self, 'callback') and self.callback     is not None

    @property
    def has_level       (self) -> bool: return hasattr(self, 'level'   ) and self.level        is not None

    @property
    def has_Handler     (self) -> bool: return hasattr(self, 'Handler' ) and self.Handler      is not None

    @property
    def has_Buffer      (self) -> bool: return hasattr(self, 'Buffer'  ) and self.Buffer       is not None
