"""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 .CircleAnnotation import CircleAnnotation
from .PointsAnnotation import PointsAnnotation
from .TextAnnotation import TextAnnotation


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

    __slots__ = [
        "circles_length",
        "points_length",
        "texts_length",
        "circles",
        "points",
        "texts",
    ]

    __typenames__ = [
        "int32_t",
        "int32_t",
        "int32_t",
        "CircleAnnotation",
        "PointsAnnotation",
        "TextAnnotation",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        ["circles_length"],
        ["points_length"],
        ["texts_length"],
    ]

    circles_length: "int32_t"
    points_length: "int32_t"
    texts_length: "int32_t"
    circles: CircleAnnotation
    points: PointsAnnotation
    texts: TextAnnotation

    def __init__(
        self,
        circles_length=0,
        points_length=0,
        texts_length=0,
        circles=[],
        points=[],
        texts=[],
    ):
        # LCM Type: int32_t
        self.circles_length = circles_length
        # LCM Type: int32_t
        self.points_length = points_length
        # LCM Type: int32_t
        self.texts_length = texts_length
        # LCM Type: CircleAnnotation[circles_length]
        self.circles = circles
        # LCM Type: PointsAnnotation[points_length]
        self.points = points
        # LCM Type: TextAnnotation[texts_length]
        self.texts = texts

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

    def _encode_one(self, buf):
        buf.write(
            struct.pack(
                ">iii", self.circles_length, self.points_length, self.texts_length
            )
        )
        for i0 in range(self.circles_length):
            assert (
                self.circles[i0]._get_packed_fingerprint()
                == CircleAnnotation._get_packed_fingerprint()
            )
            self.circles[i0]._encode_one(buf)
        for i0 in range(self.points_length):
            assert (
                self.points[i0]._get_packed_fingerprint()
                == PointsAnnotation._get_packed_fingerprint()
            )
            self.points[i0]._encode_one(buf)
        for i0 in range(self.texts_length):
            assert (
                self.texts[i0]._get_packed_fingerprint()
                == TextAnnotation._get_packed_fingerprint()
            )
            self.texts[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.circles_length, self.points_length, self.texts_length = struct.unpack(
            ">iii", buf.read(12)
        )
        self.circles = []
        for i0 in range(self.circles_length):
            self.circles.append(cls._get_field_type("circles")._decode_one(buf))
        self.points = []
        for i0 in range(self.points_length):
            self.points.append(cls._get_field_type("points")._decode_one(buf))
        self.texts = []
        for i0 in range(self.texts_length):
            self.texts.append(cls._get_field_type("texts")._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 = (
            0x8B3A52C632C59B07
            + CircleAnnotation._get_hash_recursive(newparents)
            + PointsAnnotation._get_hash_recursive(newparents)
            + TextAnnotation._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]
