# auto generated by update_py.py

import ctypes

from tlclient.linker.utility import bytify


class FrameHeaderStatus(object):
    NORMAL = 1
    HAS_NEXT = 2
    IS_BUFFER = 10
    PB = 20


class FrameHeader(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ('status', ctypes.c_byte),
        ('msg_type', ctypes.c_short),
        ('length', ctypes.c_size_t),
        ('nano', ctypes.c_int64),
        ('source', ctypes.c_int),
        ('req_id', ctypes.c_int64),
        ('err_id', ctypes.c_int),
        ('topic', ctypes.c_short),
    ]


class Frame:

    SIZE_OF_HEADER = ctypes.sizeof(FrameHeader)

    def __init__(self, recv_s=None):
        if recv_s is None:
            self.frame = FrameHeader()
            self._data_addr = None
            self.buf_s = None
        else:
            self.parse_str(recv_s)

    def parse_str(self, s: bytes):
        if not isinstance(s, bytes):
            self.buf_s = bytes(s)
        else:
            self.buf_s = s
        self.frame = ctypes.cast(ctypes.c_char_p(self.buf_s), ctypes.POINTER(FrameHeader)).contents
        self._data_addr = ctypes.addressof(self.frame) + self.SIZE_OF_HEADER

    # getters
    def get_status(self):
        return self.frame.status

    def get_length(self):
        return self.frame.length

    def get_msg_type(self):
        return self.frame.msg_type

    def get_nano(self):
        return self.frame.nano

    def get_source(self):
        return self.frame.source

    def size(self):
        return self.get_length()

    def get_req_id(self):
        return self.frame.req_id

    def get_err_id(self):
        return self.frame.err_id

    def get_subscribe_topic(self):
        return self.frame.topic

    # setters
    def set_status(self, s):
        self.frame.status = s

    def set_length(self, l):
        self.frame.length = l

    def set_data_length(self, dl):
        self.frame.length = dl + self.get_header_length()

    def set_msg_type(self, m):
        self.frame.msg_type = m

    def set_nano(self, n):
        self.frame.nano = n

    def set_source(self, s):
        self.frame.source = s

    def set_req_id(self, rid):
        self.frame.req_id = rid

    def set_err_id(self, eid):
        self.frame.err_id = eid

    def set_subscribe_topic(self, topic):
        self.frame.topic = topic

    # get data
    def get_header_length(self):
        return self.SIZE_OF_HEADER

    def get_data_length(self):
        return self.get_length() - self.get_header_length()

    def get_data_ptr(self):
        return self._data_addr

    def get_frame_ptr(self):
        return ctypes.addressof(self.frame)

    # set data
    def set_data(self, ctype_obj, length=None):
        if isinstance(ctype_obj, str):
            self.set_string(ctype_obj)
            return
        length = None or ctypes.sizeof(ctype_obj)
        self.set_data_length(length)
        self.buf = bytearray(self.frame)
        self.buf.extend((ctypes.c_char * length).from_buffer(ctype_obj))
        self.parse_str(self.buf)

    # complex
    def get_string(self):
        if self._data_addr == None:
            return None
        # return ctypes.cast(self._data_addr, ctypes.c_char_p).value
        return self.buf_s[self.SIZE_OF_HEADER:self.frame.length]

    def get_int64(self):
        if self._data_addr == None:
            return None
        return ctypes.cast(self._data_addr, ctypes.POINTER(ctypes.c_int64)).value

    def set_string(self, s):
        self.set_data_length(len(s))
        self.buf = bytearray(self.frame)
        self.buf.extend(bytify(s))
        self.parse_str(self.buf)

    def get_obj(self, CAST_TYPE):
        return ctypes.cast(self.get_data_ptr(), ctypes.POINTER(CAST_TYPE)).contents
