"""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 geometry_msgs
from lcm_msgs import std_msgs


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

    __slots__ = [
        "joint_names_length",
        "transforms_length",
        "twist_length",
        "wrench_length",
        "header",
        "joint_names",
        "transforms",
        "twist",
        "wrench",
    ]

    __typenames__ = [
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "std_msgs.Header",
        "string",
        "geometry_msgs.Transform",
        "geometry_msgs.Twist",
        "geometry_msgs.Wrench",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        ["joint_names_length"],
        ["transforms_length"],
        ["twist_length"],
        ["wrench_length"],
    ]

    joint_names_length: "int32_t"
    transforms_length: "int32_t"
    twist_length: "int32_t"
    wrench_length: "int32_t"
    header: std_msgs.Header
    joint_names: "string"
    transforms: geometry_msgs.Transform
    twist: geometry_msgs.Twist
    wrench: geometry_msgs.Wrench

    def __init__(
        self,
        joint_names_length=0,
        transforms_length=0,
        twist_length=0,
        wrench_length=0,
        header=std_msgs.Header(),
        joint_names=[],
        transforms=[],
        twist=[],
        wrench=[],
    ):
        # LCM Type: int32_t
        self.joint_names_length = joint_names_length
        # LCM Type: int32_t
        self.transforms_length = transforms_length
        # LCM Type: int32_t
        self.twist_length = twist_length
        # LCM Type: int32_t
        self.wrench_length = wrench_length
        # LCM Type: std_msgs.Header
        self.header = header
        # LCM Type: string[joint_names_length]
        self.joint_names = joint_names
        # LCM Type: geometry_msgs.Transform[transforms_length]
        self.transforms = transforms
        # LCM Type: geometry_msgs.Twist[twist_length]
        self.twist = twist
        # LCM Type: geometry_msgs.Wrench[wrench_length]
        self.wrench = wrench

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

    def _encode_one(self, buf):
        buf.write(
            struct.pack(
                ">iiii",
                self.joint_names_length,
                self.transforms_length,
                self.twist_length,
                self.wrench_length,
            )
        )
        assert (
            self.header._get_packed_fingerprint()
            == std_msgs.Header._get_packed_fingerprint()
        )
        self.header._encode_one(buf)
        for i0 in range(self.joint_names_length):
            __joint_names_encoded = self.joint_names[i0].encode("utf-8")
            buf.write(struct.pack(">I", len(__joint_names_encoded) + 1))
            buf.write(__joint_names_encoded)
            buf.write(b"\0")
        for i0 in range(self.transforms_length):
            assert (
                self.transforms[i0]._get_packed_fingerprint()
                == geometry_msgs.Transform._get_packed_fingerprint()
            )
            self.transforms[i0]._encode_one(buf)
        for i0 in range(self.twist_length):
            assert (
                self.twist[i0]._get_packed_fingerprint()
                == geometry_msgs.Twist._get_packed_fingerprint()
            )
            self.twist[i0]._encode_one(buf)
        for i0 in range(self.wrench_length):
            assert (
                self.wrench[i0]._get_packed_fingerprint()
                == geometry_msgs.Wrench._get_packed_fingerprint()
            )
            self.wrench[i0]._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.joint_names_length,
            self.transforms_length,
            self.twist_length,
            self.wrench_length,
        ) = struct.unpack(">iiii", buf.read(16))
        self.header = cls._get_field_type("header")._decode_one(buf)
        self.joint_names = []
        for i0 in range(self.joint_names_length):
            __joint_names_len = struct.unpack(">I", buf.read(4))[0]
            self.joint_names.append(
                buf.read(__joint_names_len)[:-1].decode("utf-8", "replace")
            )
        self.transforms = []
        for i0 in range(self.transforms_length):
            self.transforms.append(cls._get_field_type("transforms")._decode_one(buf))
        self.twist = []
        for i0 in range(self.twist_length):
            self.twist.append(cls._get_field_type("twist")._decode_one(buf))
        self.wrench = []
        for i0 in range(self.wrench_length):
            self.wrench.append(cls._get_field_type("wrench")._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 = (
            0x15CA331F6F9F4FBC
            + std_msgs.Header._get_hash_recursive(newparents)
            + geometry_msgs.Transform._get_hash_recursive(newparents)
            + geometry_msgs.Twist._get_hash_recursive(newparents)
            + geometry_msgs.Wrench._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]
