"""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 lcm_msgs import builtin_interfaces
from .KeyValuePair import KeyValuePair
from .ArrowPrimitive import ArrowPrimitive
from .LinePrimitive import LinePrimitive
from .TriangleListPrimitive import TriangleListPrimitive
from .TextPrimitive import TextPrimitive
from .CubePrimitive import CubePrimitive
from .SpherePrimitive import SpherePrimitive
from .CylinderPrimitive import CylinderPrimitive
from .ModelPrimitive import ModelPrimitive


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

    __slots__ = [
        "metadata_length",
        "arrows_length",
        "cubes_length",
        "spheres_length",
        "cylinders_length",
        "lines_length",
        "triangles_length",
        "texts_length",
        "models_length",
        "timestamp",
        "frame_id",
        "id",
        "lifetime",
        "frame_locked",
        "metadata",
        "arrows",
        "cubes",
        "spheres",
        "cylinders",
        "lines",
        "triangles",
        "texts",
        "models",
    ]

    __typenames__ = [
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "int32_t",
        "builtin_interfaces.Time",
        "string",
        "string",
        "builtin_interfaces.Duration",
        "boolean",
        "KeyValuePair",
        "ArrowPrimitive",
        "CubePrimitive",
        "SpherePrimitive",
        "CylinderPrimitive",
        "LinePrimitive",
        "TriangleListPrimitive",
        "TextPrimitive",
        "ModelPrimitive",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        ["metadata_length"],
        ["arrows_length"],
        ["cubes_length"],
        ["spheres_length"],
        ["cylinders_length"],
        ["lines_length"],
        ["triangles_length"],
        ["texts_length"],
        ["models_length"],
    ]

    metadata_length: "int32_t"
    arrows_length: "int32_t"
    cubes_length: "int32_t"
    spheres_length: "int32_t"
    cylinders_length: "int32_t"
    lines_length: "int32_t"
    triangles_length: "int32_t"
    texts_length: "int32_t"
    models_length: "int32_t"
    timestamp: builtin_interfaces.Time
    frame_id: "string"
    id: "string"
    lifetime: builtin_interfaces.Duration
    frame_locked: "boolean"
    metadata: KeyValuePair
    arrows: ArrowPrimitive
    cubes: CubePrimitive
    spheres: SpherePrimitive
    cylinders: CylinderPrimitive
    lines: LinePrimitive
    triangles: TriangleListPrimitive
    texts: TextPrimitive
    models: ModelPrimitive

    def __init__(
        self,
        metadata_length=0,
        arrows_length=0,
        cubes_length=0,
        spheres_length=0,
        cylinders_length=0,
        lines_length=0,
        triangles_length=0,
        texts_length=0,
        models_length=0,
        timestamp=builtin_interfaces.Time(),
        frame_id="",
        id="",
        lifetime=builtin_interfaces.Duration(),
        frame_locked=False,
        metadata=[],
        arrows=[],
        cubes=[],
        spheres=[],
        cylinders=[],
        lines=[],
        triangles=[],
        texts=[],
        models=[],
    ):
        # LCM Type: int32_t
        self.metadata_length = metadata_length
        # LCM Type: int32_t
        self.arrows_length = arrows_length
        # LCM Type: int32_t
        self.cubes_length = cubes_length
        # LCM Type: int32_t
        self.spheres_length = spheres_length
        # LCM Type: int32_t
        self.cylinders_length = cylinders_length
        # LCM Type: int32_t
        self.lines_length = lines_length
        # LCM Type: int32_t
        self.triangles_length = triangles_length
        # LCM Type: int32_t
        self.texts_length = texts_length
        # LCM Type: int32_t
        self.models_length = models_length
        # LCM Type: builtin_interfaces.Time
        self.timestamp = timestamp
        # LCM Type: string
        self.frame_id = frame_id
        # LCM Type: string
        self.id = id
        # LCM Type: builtin_interfaces.Duration
        self.lifetime = lifetime
        # LCM Type: boolean
        self.frame_locked = frame_locked
        # LCM Type: KeyValuePair[metadata_length]
        self.metadata = metadata
        # LCM Type: ArrowPrimitive[arrows_length]
        self.arrows = arrows
        # LCM Type: CubePrimitive[cubes_length]
        self.cubes = cubes
        # LCM Type: SpherePrimitive[spheres_length]
        self.spheres = spheres
        # LCM Type: CylinderPrimitive[cylinders_length]
        self.cylinders = cylinders
        # LCM Type: LinePrimitive[lines_length]
        self.lines = lines
        # LCM Type: TriangleListPrimitive[triangles_length]
        self.triangles = triangles
        # LCM Type: TextPrimitive[texts_length]
        self.texts = texts
        # LCM Type: ModelPrimitive[models_length]
        self.models = models

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

    def _encode_one(self, buf):
        buf.write(
            struct.pack(
                ">iiiiiiiii",
                self.metadata_length,
                self.arrows_length,
                self.cubes_length,
                self.spheres_length,
                self.cylinders_length,
                self.lines_length,
                self.triangles_length,
                self.texts_length,
                self.models_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")
        __id_encoded = self.id.encode("utf-8")
        buf.write(struct.pack(">I", len(__id_encoded) + 1))
        buf.write(__id_encoded)
        buf.write(b"\0")
        assert (
            self.lifetime._get_packed_fingerprint()
            == builtin_interfaces.Duration._get_packed_fingerprint()
        )
        self.lifetime._encode_one(buf)
        buf.write(struct.pack(">b", self.frame_locked))
        for i0 in range(self.metadata_length):
            assert (
                self.metadata[i0]._get_packed_fingerprint()
                == KeyValuePair._get_packed_fingerprint()
            )
            self.metadata[i0]._encode_one(buf)
        for i0 in range(self.arrows_length):
            assert (
                self.arrows[i0]._get_packed_fingerprint()
                == ArrowPrimitive._get_packed_fingerprint()
            )
            self.arrows[i0]._encode_one(buf)
        for i0 in range(self.cubes_length):
            assert (
                self.cubes[i0]._get_packed_fingerprint()
                == CubePrimitive._get_packed_fingerprint()
            )
            self.cubes[i0]._encode_one(buf)
        for i0 in range(self.spheres_length):
            assert (
                self.spheres[i0]._get_packed_fingerprint()
                == SpherePrimitive._get_packed_fingerprint()
            )
            self.spheres[i0]._encode_one(buf)
        for i0 in range(self.cylinders_length):
            assert (
                self.cylinders[i0]._get_packed_fingerprint()
                == CylinderPrimitive._get_packed_fingerprint()
            )
            self.cylinders[i0]._encode_one(buf)
        for i0 in range(self.lines_length):
            assert (
                self.lines[i0]._get_packed_fingerprint()
                == LinePrimitive._get_packed_fingerprint()
            )
            self.lines[i0]._encode_one(buf)
        for i0 in range(self.triangles_length):
            assert (
                self.triangles[i0]._get_packed_fingerprint()
                == TriangleListPrimitive._get_packed_fingerprint()
            )
            self.triangles[i0]._encode_one(buf)
        for i0 in range(self.texts_length):
            assert (
                self.texts[i0]._get_packed_fingerprint()
                == TextPrimitive._get_packed_fingerprint()
            )
            self.texts[i0]._encode_one(buf)
        for i0 in range(self.models_length):
            assert (
                self.models[i0]._get_packed_fingerprint()
                == ModelPrimitive._get_packed_fingerprint()
            )
            self.models[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.metadata_length,
            self.arrows_length,
            self.cubes_length,
            self.spheres_length,
            self.cylinders_length,
            self.lines_length,
            self.triangles_length,
            self.texts_length,
            self.models_length,
        ) = struct.unpack(">iiiiiiiii", buf.read(36))
        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")
        __id_len = struct.unpack(">I", buf.read(4))[0]
        self.id = buf.read(__id_len)[:-1].decode("utf-8", "replace")
        self.lifetime = cls._get_field_type("lifetime")._decode_one(buf)
        self.frame_locked = bool(struct.unpack("b", buf.read(1))[0])
        self.metadata = []
        for i0 in range(self.metadata_length):
            self.metadata.append(cls._get_field_type("metadata")._decode_one(buf))
        self.arrows = []
        for i0 in range(self.arrows_length):
            self.arrows.append(cls._get_field_type("arrows")._decode_one(buf))
        self.cubes = []
        for i0 in range(self.cubes_length):
            self.cubes.append(cls._get_field_type("cubes")._decode_one(buf))
        self.spheres = []
        for i0 in range(self.spheres_length):
            self.spheres.append(cls._get_field_type("spheres")._decode_one(buf))
        self.cylinders = []
        for i0 in range(self.cylinders_length):
            self.cylinders.append(cls._get_field_type("cylinders")._decode_one(buf))
        self.lines = []
        for i0 in range(self.lines_length):
            self.lines.append(cls._get_field_type("lines")._decode_one(buf))
        self.triangles = []
        for i0 in range(self.triangles_length):
            self.triangles.append(cls._get_field_type("triangles")._decode_one(buf))
        self.texts = []
        for i0 in range(self.texts_length):
            self.texts.append(cls._get_field_type("texts")._decode_one(buf))
        self.models = []
        for i0 in range(self.models_length):
            self.models.append(cls._get_field_type("models")._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 = (
            0xE143D679579F0AB0
            + builtin_interfaces.Time._get_hash_recursive(newparents)
            + builtin_interfaces.Duration._get_hash_recursive(newparents)
            + KeyValuePair._get_hash_recursive(newparents)
            + ArrowPrimitive._get_hash_recursive(newparents)
            + CubePrimitive._get_hash_recursive(newparents)
            + SpherePrimitive._get_hash_recursive(newparents)
            + CylinderPrimitive._get_hash_recursive(newparents)
            + LinePrimitive._get_hash_recursive(newparents)
            + TriangleListPrimitive._get_hash_recursive(newparents)
            + TextPrimitive._get_hash_recursive(newparents)
            + ModelPrimitive._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]
