"""LCM type definitions
This file automatically generated by lcm.
DO NOT MODIFY BY HAND!!!!
"""

from io import BytesIO
import struct
import sys

from lcm_msgs import std_msgs
from . import *
from .RegionOfInterest import RegionOfInterest


class CameraInfo(object):
    msg_name = "sensor_msgs.CameraInfo"

    __slots__ = [
        "D_length",
        "header",
        "height",
        "width",
        "distortion_model",
        "D",
        "K",
        "R",
        "P",
        "binning_x",
        "binning_y",
        "roi",
    ]

    __typenames__ = [
        "int32_t",
        "std_msgs.Header",
        "int32_t",
        "int32_t",
        "string",
        "double",
        "double",
        "double",
        "double",
        "int32_t",
        "int32_t",
        "RegionOfInterest",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        ["D_length"],
        [9],
        [9],
        [12],
        None,
        None,
        None,
    ]

    D_length: "int32_t"
    header: std_msgs.Header
    height: "int32_t"
    width: "int32_t"
    distortion_model: "string"
    D: "double"
    K: "double"
    R: "double"
    P: "double"
    binning_x: "int32_t"
    binning_y: "int32_t"
    roi: RegionOfInterest

    def __init__(
        self,
        D_length=0,
        header=std_msgs.Header(),
        height=0,
        width=0,
        distortion_model="",
        D=[],
        K=[0.0 for dim0 in range(9)],
        R=[0.0 for dim0 in range(9)],
        P=[0.0 for dim0 in range(12)],
        binning_x=0,
        binning_y=0,
        roi=RegionOfInterest(),
    ):
        # LCM Type: int32_t
        self.D_length = D_length
        # LCM Type: std_msgs.Header
        self.header = header
        # LCM Type: int32_t
        self.height = height
        # LCM Type: int32_t
        self.width = width
        # LCM Type: string
        self.distortion_model = distortion_model
        # LCM Type: double[D_length]
        self.D = D
        # LCM Type: double[9]
        self.K = K
        # LCM Type: double[9]
        self.R = R
        # LCM Type: double[12]
        self.P = P
        # LCM Type: int32_t
        self.binning_x = binning_x
        # LCM Type: int32_t
        self.binning_y = binning_y
        # LCM Type: RegionOfInterest
        self.roi = roi

    def lcm_encode(self):
        buf = BytesIO()
        buf.write(CameraInfo._get_packed_fingerprint())
        self._encode_one(buf)
        return buf.getvalue()

    def _encode_one(self, buf):
        buf.write(struct.pack(">i", self.D_length))
        assert (
            self.header._get_packed_fingerprint()
            == std_msgs.Header._get_packed_fingerprint()
        )
        self.header._encode_one(buf)
        buf.write(struct.pack(">ii", self.height, self.width))
        __distortion_model_encoded = self.distortion_model.encode("utf-8")
        buf.write(struct.pack(">I", len(__distortion_model_encoded) + 1))
        buf.write(__distortion_model_encoded)
        buf.write(b"\0")
        buf.write(struct.pack(">%dd" % self.D_length, *self.D[: self.D_length]))
        buf.write(struct.pack(">9d", *self.K[:9]))
        buf.write(struct.pack(">9d", *self.R[:9]))
        buf.write(struct.pack(">12d", *self.P[:12]))
        buf.write(struct.pack(">ii", self.binning_x, self.binning_y))
        assert (
            self.roi._get_packed_fingerprint()
            == RegionOfInterest._get_packed_fingerprint()
        )
        self.roi._encode_one(buf)

    @classmethod
    def lcm_decode(cls, data: bytes):
        if hasattr(data, "read"):
            buf = data
        else:
            buf = BytesIO(data)
        if buf.read(8) != cls._get_packed_fingerprint():
            raise ValueError("Decode error")
        return cls._decode_one(buf)

    @classmethod
    def _decode_one(cls, buf):
        self = cls()
        self.D_length = struct.unpack(">i", buf.read(4))[0]
        self.header = cls._get_field_type("header")._decode_one(buf)
        self.height, self.width = struct.unpack(">ii", buf.read(8))
        __distortion_model_len = struct.unpack(">I", buf.read(4))[0]
        self.distortion_model = buf.read(__distortion_model_len)[:-1].decode(
            "utf-8", "replace"
        )
        self.D = struct.unpack(">%dd" % self.D_length, buf.read(self.D_length * 8))
        self.K = struct.unpack(">9d", buf.read(72))
        self.R = struct.unpack(">9d", buf.read(72))
        self.P = struct.unpack(">12d", buf.read(96))
        self.binning_x, self.binning_y = struct.unpack(">ii", buf.read(8))
        self.roi = cls._get_field_type("roi")._decode_one(buf)
        return self

    @classmethod
    def _get_field_type(cls, field_name):
        """Get the type for a field from annotations."""
        annotation = cls.__annotations__.get(field_name)
        if annotation is None:
            return None
        if isinstance(annotation, str):
            module = sys.modules[cls.__module__]
            if hasattr(module, annotation):
                return getattr(module, annotation)
            return None
        return annotation

    @classmethod
    def _get_hash_recursive(cls, parents):
        if cls in parents:
            return 0
        newparents = parents + [cls]
        tmphash = (
            0xB4EA6258BC6D0702
            + std_msgs.Header._get_hash_recursive(newparents)
            + RegionOfInterest._get_hash_recursive(newparents)
        ) & 0xFFFFFFFFFFFFFFFF
        tmphash = (
            ((tmphash << 1) & 0xFFFFFFFFFFFFFFFF) + (tmphash >> 63)
        ) & 0xFFFFFFFFFFFFFFFF
        return tmphash

    _packed_fingerprint = None

    @classmethod
    def _get_packed_fingerprint(cls):
        if cls._packed_fingerprint is None:
            cls._packed_fingerprint = struct.pack(">Q", cls._get_hash_recursive([]))
        return cls._packed_fingerprint

    def get_hash(self):
        """Get the LCM hash of the struct"""
        return struct.unpack(">Q", cls._get_packed_fingerprint())[0]
