"""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 builtin_interfaces


class CameraCalibration(object):
    msg_name = "foxglove_msgs.CameraCalibration"

    __slots__ = [
        "d_length",
        "timestamp",
        "frame_id",
        "width",
        "height",
        "distortion_model",
        "d",
        "k",
        "r",
        "p",
    ]

    __typenames__ = [
        "int32_t",
        "builtin_interfaces.Time",
        "string",
        "int32_t",
        "int32_t",
        "string",
        "double",
        "double",
        "double",
        "double",
    ]

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

    d_length: "int32_t"
    timestamp: builtin_interfaces.Time
    frame_id: "string"
    width: "int32_t"
    height: "int32_t"
    distortion_model: "string"
    d: "double"
    k: "double"
    r: "double"
    p: "double"

    def __init__(
        self,
        d_length=0,
        timestamp=builtin_interfaces.Time(),
        frame_id="",
        width=0,
        height=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)],
    ):
        # LCM Type: int32_t
        self.d_length = d_length
        # LCM Type: builtin_interfaces.Time
        self.timestamp = timestamp
        # LCM Type: string
        self.frame_id = frame_id
        # LCM Type: int32_t
        self.width = width
        # LCM Type: int32_t
        self.height = height
        # 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

    def lcm_encode(self):
        buf = BytesIO()
        buf.write(CameraCalibration._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.timestamp._get_packed_fingerprint()
            == builtin_interfaces.Time._get_packed_fingerprint()
        )
        self.timestamp._encode_one(buf)
        __frame_id_encoded = self.frame_id.encode("utf-8")
        buf.write(struct.pack(">I", len(__frame_id_encoded) + 1))
        buf.write(__frame_id_encoded)
        buf.write(b"\0")
        buf.write(struct.pack(">ii", self.width, self.height))
        __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]))

    @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.timestamp = cls._get_field_type("timestamp")._decode_one(buf)
        __frame_id_len = struct.unpack(">I", buf.read(4))[0]
        self.frame_id = buf.read(__frame_id_len)[:-1].decode("utf-8", "replace")
        self.width, self.height = 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))
        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 = (
            0x89C275083A857CE2 + builtin_interfaces.Time._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]
