# auto generated by update_py.py

import ctypes
from tlclient.linker.constant import SubscribeTopic
from tlclient.linker.frame import FrameHeaderStatus
import tlclient.linker.frame_pb2 as frame_pb2


class MemBufferHeader(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ('status', ctypes.c_byte),
        ('frame_num', ctypes.c_int64),
        ('length', ctypes.c_int64),
        ('topic', ctypes.c_short),
    ]


class MemBuffer:

    HEADER_LENGTH = ctypes.sizeof(MemBufferHeader)

    def __init__(self, length=None, buffer=None):
        if buffer is None:
            # init from new
            self._len = self.HEADER_LENGTH + length
            self._buffer = bytearray(self._len)
            self._header = MemBufferHeader()
            self._header.length = 0
            self.init()
        else:
            if not isinstance(buffer, bytearray):
                self._buffer = bytearray(buffer)
            else:
                self._buffer = buffer
            self._tmp_header = bytes(self._buffer[:self.HEADER_LENGTH])
            self._header = ctypes.cast(ctypes.c_char_p(self._tmp_header), ctypes.POINTER(MemBufferHeader)).contents
            self._len = self._header.length

    def init(self):
        self._header.status = FrameHeaderStatus.IS_BUFFER
        self._header.frame_num = 0
        self._header.length = self.cur_frame_idx = self.HEADER_LENGTH
        self._header.topic = SubscribeTopic.UNEXPECTED

    def get_length(self):
        return self._len

    def get_actual_length(self):
        return self._header.length

    def get_frame_num(self):
        return self._header.frame_num

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

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

    def append(self, start_idx, frame):
        end_idx = start_idx + frame.get_length()
        self._buffer[start_idx: end_idx] = frame.buf[:frame.get_length()]
        self.cur_frame_idx = start_idx
        self._buffer[start_idx] = FrameHeaderStatus.HAS_NEXT
        self._header.frame_num += 1
        self._header.length = end_idx
        return end_idx

    def finalize(self):
        self._buffer[self.cur_frame_idx] = FrameHeaderStatus.NORMAL
        header_buffer = (ctypes.c_char * self.HEADER_LENGTH).from_buffer(self._header)
        self._buffer[:self.HEADER_LENGTH] = header_buffer[:self.HEADER_LENGTH]


class PBMemBuffer:
    def __init__(self):
        self._mem_buffer = frame_pb2.MemBuffer()

    def init(self):
        self._mem_buffer.ClearField("content_id")
        self._mem_buffer.ClearField("frames")

    def empty(self):
        return len(self._mem_buffer.frames) == 0

    def get_content_id(self):
        return self._mem_buffer.content_id

    def set_content_id(self, content_id: str):
        self._mem_buffer.content_id = content_id

    def append(self, e):
        self._mem_buffer.frames.append(e._frame)

    @property
    def buf(self):
        return (FrameHeaderStatus.PB).to_bytes(1, byteorder='little') + self._mem_buffer.SerializeToString()
