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


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

    __slots__ = [
        "name_length",
        "position_length",
        "velocity_length",
        "effort_length",
        "header",
        "name",
        "position",
        "velocity",
        "effort",
    ]

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

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        ["name_length"],
        ["position_length"],
        ["velocity_length"],
        ["effort_length"],
    ]

    name_length: "int32_t"
    position_length: "int32_t"
    velocity_length: "int32_t"
    effort_length: "int32_t"
    header: std_msgs.Header
    name: "string"
    position: "double"
    velocity: "double"
    effort: "double"

    def __init__(
        self,
        name_length=0,
        position_length=0,
        velocity_length=0,
        effort_length=0,
        header=std_msgs.Header(),
        name=[],
        position=[],
        velocity=[],
        effort=[],
    ):
        # LCM Type: int32_t
        self.name_length = name_length
        # LCM Type: int32_t
        self.position_length = position_length
        # LCM Type: int32_t
        self.velocity_length = velocity_length
        # LCM Type: int32_t
        self.effort_length = effort_length
        # LCM Type: std_msgs.Header
        self.header = header
        # LCM Type: string[name_length]
        self.name = name
        # LCM Type: double[position_length]
        self.position = position
        # LCM Type: double[velocity_length]
        self.velocity = velocity
        # LCM Type: double[effort_length]
        self.effort = effort

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

    def _encode_one(self, buf):
        buf.write(
            struct.pack(
                ">iiii",
                self.name_length,
                self.position_length,
                self.velocity_length,
                self.effort_length,
            )
        )
        assert (
            self.header._get_packed_fingerprint()
            == std_msgs.Header._get_packed_fingerprint()
        )
        self.header._encode_one(buf)
        for i0 in range(self.name_length):
            __name_encoded = self.name[i0].encode("utf-8")
            buf.write(struct.pack(">I", len(__name_encoded) + 1))
            buf.write(__name_encoded)
            buf.write(b"\0")
        buf.write(
            struct.pack(
                ">%dd" % self.position_length, *self.position[: self.position_length]
            )
        )
        buf.write(
            struct.pack(
                ">%dd" % self.velocity_length, *self.velocity[: self.velocity_length]
            )
        )
        buf.write(
            struct.pack(">%dd" % self.effort_length, *self.effort[: self.effort_length])
        )

    @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.name_length,
            self.position_length,
            self.velocity_length,
            self.effort_length,
        ) = struct.unpack(">iiii", buf.read(16))
        self.header = cls._get_field_type("header")._decode_one(buf)
        self.name = []
        for i0 in range(self.name_length):
            __name_len = struct.unpack(">I", buf.read(4))[0]
            self.name.append(buf.read(__name_len)[:-1].decode("utf-8", "replace"))
        self.position = struct.unpack(
            ">%dd" % self.position_length, buf.read(self.position_length * 8)
        )
        self.velocity = struct.unpack(
            ">%dd" % self.velocity_length, buf.read(self.velocity_length * 8)
        )
        self.effort = struct.unpack(
            ">%dd" % self.effort_length, buf.read(self.effort_length * 8)
        )
        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 = (
            0xB69CC30D0D7668FA + std_msgs.Header._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]
