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

from io import BytesIO
import struct
import sys

from . import *
from .InteractiveMarkerPose import InteractiveMarkerPose
from .InteractiveMarker import InteractiveMarker


class InteractiveMarkerUpdate(object):
    msg_name = "InteractiveMarkerUpdate"

    __slots__ = [
        "markers_length",
        "poses_length",
        "erases_length",
        "server_id",
        "seq_num",
        "type",
        "markers",
        "poses",
        "erases",
    ]

    __typenames__ = [
        "int32_t",
        "int32_t",
        "int32_t",
        "string",
        "int64_t",
        "byte",
        "InteractiveMarker",
        "InteractiveMarkerPose",
        "string",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        None,
        ["markers_length"],
        ["poses_length"],
        ["erases_length"],
    ]

    markers_length: "int32_t"
    poses_length: "int32_t"
    erases_length: "int32_t"
    server_id: "string"
    seq_num: "int64_t"
    type: "byte"
    markers: InteractiveMarker
    poses: InteractiveMarkerPose
    erases: "string"

    KEEP_ALIVE = 0
    UPDATE = 1

    def __init__(
        self,
        markers_length=0,
        poses_length=0,
        erases_length=0,
        server_id="",
        seq_num=0,
        type=0,
        markers=[],
        poses=[],
        erases=[],
    ):
        # LCM Type: int32_t
        self.markers_length = markers_length
        # LCM Type: int32_t
        self.poses_length = poses_length
        # LCM Type: int32_t
        self.erases_length = erases_length
        # LCM Type: string
        self.server_id = server_id
        # LCM Type: int64_t
        self.seq_num = seq_num
        # LCM Type: byte
        self.type = type
        # LCM Type: InteractiveMarker[markers_length]
        self.markers = markers
        # LCM Type: InteractiveMarkerPose[poses_length]
        self.poses = poses
        # LCM Type: string[erases_length]
        self.erases = erases

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

    def _encode_one(self, buf):
        buf.write(
            struct.pack(
                ">iii", self.markers_length, self.poses_length, self.erases_length
            )
        )
        __server_id_encoded = self.server_id.encode("utf-8")
        buf.write(struct.pack(">I", len(__server_id_encoded) + 1))
        buf.write(__server_id_encoded)
        buf.write(b"\0")
        buf.write(struct.pack(">qB", self.seq_num, self.type))
        for i0 in range(self.markers_length):
            assert (
                self.markers[i0]._get_packed_fingerprint()
                == InteractiveMarker._get_packed_fingerprint()
            )
            self.markers[i0]._encode_one(buf)
        for i0 in range(self.poses_length):
            assert (
                self.poses[i0]._get_packed_fingerprint()
                == InteractiveMarkerPose._get_packed_fingerprint()
            )
            self.poses[i0]._encode_one(buf)
        for i0 in range(self.erases_length):
            __erases_encoded = self.erases[i0].encode("utf-8")
            buf.write(struct.pack(">I", len(__erases_encoded) + 1))
            buf.write(__erases_encoded)
            buf.write(b"\0")

    @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.markers_length, self.poses_length, self.erases_length = struct.unpack(
            ">iii", buf.read(12)
        )
        __server_id_len = struct.unpack(">I", buf.read(4))[0]
        self.server_id = buf.read(__server_id_len)[:-1].decode("utf-8", "replace")
        self.seq_num, self.type = struct.unpack(">qB", buf.read(9))
        self.markers = []
        for i0 in range(self.markers_length):
            self.markers.append(cls._get_field_type("markers")._decode_one(buf))
        self.poses = []
        for i0 in range(self.poses_length):
            self.poses.append(cls._get_field_type("poses")._decode_one(buf))
        self.erases = []
        for i0 in range(self.erases_length):
            __erases_len = struct.unpack(">I", buf.read(4))[0]
            self.erases.append(buf.read(__erases_len)[:-1].decode("utf-8", "replace"))
        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 = (
            0xF6EEBB4C4A608B4C
            + InteractiveMarker._get_hash_recursive(newparents)
            + InteractiveMarkerPose._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]
