"""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 LaserScan(object):
    msg_name = "sensor_msgs.LaserScan"

    __slots__ = [
        "ranges_length",
        "intensities_length",
        "header",
        "angle_min",
        "angle_max",
        "angle_increment",
        "time_increment",
        "scan_time",
        "range_min",
        "range_max",
        "ranges",
        "intensities",
    ]

    __typenames__ = [
        "int32_t",
        "int32_t",
        "std_msgs.Header",
        "float",
        "float",
        "float",
        "float",
        "float",
        "float",
        "float",
        "float",
        "float",
    ]

    __dimensions__ = [
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        None,
        ["ranges_length"],
        ["intensities_length"],
    ]

    ranges_length: "int32_t"
    intensities_length: "int32_t"
    header: std_msgs.Header
    angle_min: "float"
    angle_max: "float"
    angle_increment: "float"
    time_increment: "float"
    scan_time: "float"
    range_min: "float"
    range_max: "float"
    ranges: "float"
    intensities: "float"

    def __init__(
        self,
        ranges_length=0,
        intensities_length=0,
        header=std_msgs.Header(),
        angle_min=0.0,
        angle_max=0.0,
        angle_increment=0.0,
        time_increment=0.0,
        scan_time=0.0,
        range_min=0.0,
        range_max=0.0,
        ranges=[],
        intensities=[],
    ):
        # LCM Type: int32_t
        self.ranges_length = ranges_length
        # LCM Type: int32_t
        self.intensities_length = intensities_length
        # LCM Type: std_msgs.Header
        self.header = header
        # LCM Type: float
        self.angle_min = angle_min
        # LCM Type: float
        self.angle_max = angle_max
        # LCM Type: float
        self.angle_increment = angle_increment
        # LCM Type: float
        self.time_increment = time_increment
        # LCM Type: float
        self.scan_time = scan_time
        # LCM Type: float
        self.range_min = range_min
        # LCM Type: float
        self.range_max = range_max
        # LCM Type: float[ranges_length]
        self.ranges = ranges
        # LCM Type: float[intensities_length]
        self.intensities = intensities

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

    def _encode_one(self, buf):
        buf.write(struct.pack(">ii", self.ranges_length, self.intensities_length))
        assert (
            self.header._get_packed_fingerprint()
            == std_msgs.Header._get_packed_fingerprint()
        )
        self.header._encode_one(buf)
        buf.write(
            struct.pack(
                ">fffffff",
                self.angle_min,
                self.angle_max,
                self.angle_increment,
                self.time_increment,
                self.scan_time,
                self.range_min,
                self.range_max,
            )
        )
        buf.write(
            struct.pack(">%df" % self.ranges_length, *self.ranges[: self.ranges_length])
        )
        buf.write(
            struct.pack(
                ">%df" % self.intensities_length,
                *self.intensities[: self.intensities_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.ranges_length, self.intensities_length = struct.unpack(">ii", buf.read(8))
        self.header = cls._get_field_type("header")._decode_one(buf)
        (
            self.angle_min,
            self.angle_max,
            self.angle_increment,
            self.time_increment,
            self.scan_time,
            self.range_min,
            self.range_max,
        ) = struct.unpack(">fffffff", buf.read(28))
        self.ranges = struct.unpack(
            ">%df" % self.ranges_length, buf.read(self.ranges_length * 4)
        )
        self.intensities = struct.unpack(
            ">%df" % self.intensities_length, buf.read(self.intensities_length * 4)
        )
        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 = (
            0x1717A961C492E489 + 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]
