from typing import List
from ctypes import c_uint64, c_uint32, c_uint8
from enum import IntEnum

from UniTAP.libs.lib_tsi.tsi_types import TSI_R_MEMORY_SIZE, TSI_MEMORY_LAYOUT,\
    TSI_MEMORY_BLOCK_INDEX, TSI_MEMORY_RESET_W, TSI_MEMORY_WRITE_W
from UniTAP.libs.lib_tsi.tsi import TSIX_TS_GetConfigItem, TSIX_TS_SetConfigItem
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO


class MemoryManager:
    class MemoryOwner(IntEnum):
        MO_PatternGenerator = 0
        MO_AudioGenerator = 1
        MO_Events = 2

    MAX_BLOCK_COUNT = 4

    DEFAULT_MEMOTY_ALLOCATION = [534600704, 534600704, 534600704]
    RESERVED_MEMORY_BYTES = 8192 * (5120 + 1) * 4 + 0x80000

    def __init__(self, io: DeviceIO):
        self.__io = io

    def get_total_memory(self) -> int:
        result = self.__io.get(TSI_R_MEMORY_SIZE, c_uint64)[1]
        return result

    def set_memory_layout(self, layout: List[int]):
        self.__io.set(TSI_MEMORY_LAYOUT, layout, c_uint64, data_count=len(layout))

    def get_memory_layout(self) -> List[int]:
        return self.__io.get(TSI_MEMORY_LAYOUT, c_uint64, self.MAX_BLOCK_COUNT)

    def set_memory_block_index(self, index: MemoryOwner):
        self.__io.set(TSI_MEMORY_BLOCK_INDEX, index.value)

    def make_default(self):
        self.__io.set(TSI_MEMORY_LAYOUT, self.DEFAULT_MEMOTY_ALLOCATION, c_uint64,
                      data_count=len(self.DEFAULT_MEMOTY_ALLOCATION))

    def reset(self):
        self.__io.set(TSI_MEMORY_RESET_W, 0)

    def memory_write(self, data, size):
        self.__io.set(TSI_MEMORY_WRITE_W, bytearray(data), data_type=c_uint8, data_count=size)
