"""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 .KeyValue import KeyValue


class DiagnosticStatus(object):
    msg_name = "diagnostic_msgs.DiagnosticStatus"

    __slots__ = ["values_length", "level", "name", "message", "hardware_id", "values"]

    __typenames__ = ["int32_t", "int8_t", "string", "string", "string", "KeyValue"]

    __dimensions__ = [None, None, None, None, None, ["values_length"]]

    values_length: "int32_t"
    level: "int8_t"
    name: "string"
    message: "string"
    hardware_id: "string"
    values: KeyValue

    OK = 0
    WARN = 1
    ERROR = 2
    STALE = 3

    def __init__(
        self, values_length=0, level=0, name="", message="", hardware_id="", values=[]
    ):
        # LCM Type: int32_t
        self.values_length = values_length
        # LCM Type: int8_t
        self.level = level
        # LCM Type: string
        self.name = name
        # LCM Type: string
        self.message = message
        # LCM Type: string
        self.hardware_id = hardware_id
        # LCM Type: KeyValue[values_length]
        self.values = values

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

    def _encode_one(self, buf):
        buf.write(struct.pack(">ib", self.values_length, self.level))
        __name_encoded = self.name.encode("utf-8")
        buf.write(struct.pack(">I", len(__name_encoded) + 1))
        buf.write(__name_encoded)
        buf.write(b"\0")
        __message_encoded = self.message.encode("utf-8")
        buf.write(struct.pack(">I", len(__message_encoded) + 1))
        buf.write(__message_encoded)
        buf.write(b"\0")
        __hardware_id_encoded = self.hardware_id.encode("utf-8")
        buf.write(struct.pack(">I", len(__hardware_id_encoded) + 1))
        buf.write(__hardware_id_encoded)
        buf.write(b"\0")
        for i0 in range(self.values_length):
            assert (
                self.values[i0]._get_packed_fingerprint()
                == KeyValue._get_packed_fingerprint()
            )
            self.values[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.values_length, self.level = struct.unpack(">ib", buf.read(5))
        __name_len = struct.unpack(">I", buf.read(4))[0]
        self.name = buf.read(__name_len)[:-1].decode("utf-8", "replace")
        __message_len = struct.unpack(">I", buf.read(4))[0]
        self.message = buf.read(__message_len)[:-1].decode("utf-8", "replace")
        __hardware_id_len = struct.unpack(">I", buf.read(4))[0]
        self.hardware_id = buf.read(__hardware_id_len)[:-1].decode("utf-8", "replace")
        self.values = []
        for i0 in range(self.values_length):
            self.values.append(cls._get_field_type("values")._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 = (
            0x3E3FB00C69778DFB + KeyValue._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]
