import t, c
from stdint import *
import string
import viperlib
import memhub
import hashtable
import lib.core.Handles.HandlesTranslator as HT


# ============================================================
# TypeKind - 类型种类枚举
#
# 替代 TransPyC 中 CType.position frozenset 的元属性系统。
# 每个 TypeInfo 通过 Kind 字段标记其种类，避免 Python ClassVar 反射。
# ============================================================
class TypeKind(t.CEnum):
    Basic:    t.State    # 基本类型（int/char/float/double/bool 等）
    Pointer:  t.State    # 指针（T*）— 指针层数由 TypeInfo.PtrCount 表达
    Struct:   t.State    # 结构体/类
    Union:    t.State    # 联合体
    Enum:     t.State    # 枚举
    Typedef:  t.State    # 类型别名
    Function: t.State    # 函数指针
    Array:    t.State    # 数组 T[N]
    Void:     t.State    # void


# ============================================================
# TypeInfo - 类型信息结构
#
# 设计原则（相对 TransPyC CTypeInfo 的简化）:
# - POD 数据结构，无虚函数，无 Python 元特性（ClassVar/Generic/frozenset）
# - 通过 mbuddy 分配，调用方管理生命周期（参考 llvmlite Module 模式）
# - 通过 Kind 枚举代替 position frozenset
# - PtrCount 表达指针层数（0=非指针, 1=T*, 2=T**）
# - IsSigned 三态：-1=不适用(void/float), 0=unsigned, 1=signed
#
# 字段布局（8 字段）:
#   Kind       : i32   类型种类（TypeKind 枚举值）
#   Name       : i8*   类型名（如 'int', 'CInt', 'MyStruct'），可能为 None
#   Size       : i32   位宽（0=void/未知；int=32, char=8, double=64, long long=64）
#   Align      : i32   对齐字节数（0=默认）
#   IsSigned   : i32   -1=N/A, 0=unsigned, 1=signed
#   PtrCount   : i32   指针层数
#   IsConst    : i32   const 限定符（0/1）
#   IsVolatile : i32   volatile 限定符（0/1）
#
# 注意：Size 使用位宽（bit width）而非字节数，与 LLVM IR 的 i{N} 和
# TransPyC CType.Size 约定一致（CInt.Size=32, CChar.Size=8）。
# ============================================================
@t.NoVTable
class TypeInfo:
    Kind:       int
    Name:       str
    Size:       int
    Align:      int
    IsSigned:   int
    PtrCount:   int
    IsConst:    int
    IsVolatile: int


# ============================================================
# TypeRegistry - 类型注册表
#
# 维护 name(str) → TypeInfo* 映射，基于 HashTable 实现 O(1) 查找。
# 替代 TransPyC CTypeRegistry 的 _name_to_class dict。
# 内置基本类型（int/char/void/...）由 InitBasicTypes 注册。
# ============================================================
class TypeRegistry:
    _ht: hashtable.HashTable | t.CPtr
    __mbuddy__: memhub.MemManager | t.CPtr

    def Register(self, ti: TypeInfo | t.CPtr) -> int:
        """注册一个 TypeInfo。ti.Name 字段必须已设置。

        Returns:
            1 表示成功，0 表示失败（ti 为 None 或 Name 为 None）
        """
        if ti is None:
            return 0
        if ti.Name is None:
            return 0
        self._ht[ti.Name] = ti
        return 1

    def Lookup(self, name: str) -> TypeInfo | t.CPtr:
        """按名称查找 TypeInfo。

        Returns:
            找到返回 TypeInfo*，找不到返回 None
        """
        if name is None:
            return None
        return self._ht[name]

    def Has(self, name: str) -> int:
        """检查类型是否已注册。"""
        if name is None:
            return 0
        return name in self._ht


# ============================================================
# NewTypeInfo - 工厂函数：分配并初始化一个 TypeInfo
#
# 默认值：Kind=Basic, IsSigned=-1, 其余=0/None
# ============================================================
def NewTypeInfo(pool: memhub.MemManager | t.CPtr) -> TypeInfo | t.CPtr:
    ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__())
    if ptr is None:
        return None
    string.memset(ptr, 0, TypeInfo.__sizeof__())
    ptr.Kind = TypeKind.Basic
    ptr.IsSigned = -1
    return ptr


# ============================================================
# NewTypeRegistry - 工厂函数：创建类型注册表
# ============================================================
def NewTypeRegistry(pool: memhub.MemManager | t.CPtr) -> TypeRegistry | t.CPtr:
    ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__())
    if ptr is None:
        return None
    string.memset(ptr, 0, TypeRegistry.__sizeof__())
    ptr.__mbuddy__ = pool
    ptr._ht = hashtable.HashTable(pool)
    return ptr


# ============================================================
# TypeToLLVM - 将 TypeInfo 转换为 LLVM IR 类型字符串
#
# 规则:
# - Kind == Void 或 (Size==0 且 IsSigned==-1 且 PtrCount==0) → "void"
# - void 有 PtrCount > 0 → "i8" + PtrCount 个 "*"
# - IsSigned == -1 且 Size > 0 → 浮点: half/float/double/fp128
# - IsSigned != -1 且 Size > 0 → 整数: i{Size}
# - 未知 → "i8*"
#
# Args:
#     buf: 输出缓冲区（i8*）
#     buf_size: 缓冲区容量
#     ti: TypeInfo 指针
#
# Returns:
#     写入的字符数（不含 NUL），失败返回 -1
# ============================================================
def TypeToLLVM(buf: t.CChar | t.CPtr, buf_size: t.CSizeT,
               ti: TypeInfo | t.CPtr) -> int:
    if buf is None:
        return -1
    if ti is None:
        return -1
    if buf_size == 0:
        return -1

    # 判定 void
    is_void: int = 0
    if ti.Kind == TypeKind.Void:
        is_void = 1
    elif ti.Size == 0 and ti.IsSigned == -1 and ti.PtrCount == 0:
        is_void = 1

    # 写入 base 类型字符串到 buf
    base_len: int = 0
    if is_void == 1:
        if ti.PtrCount == 0:
            # "void"
            if buf_size < 5:
                return -1
            string.strcpy(buf, "void")
            base_len = 4
        else:
            # void* → i8*（LLVM 中 void* 表示为 i8*）
            if buf_size < 4:
                return -1
            string.strcpy(buf, "i8")
            base_len = 2
    elif ti.IsSigned == -1:
        # 浮点
        if ti.Size == 16:
            if buf_size < 5:
                return -1
            string.strcpy(buf, "half")
            base_len = 4
        elif ti.Size == 32:
            if buf_size < 6:
                return -1
            string.strcpy(buf, "float")
            base_len = 5
        elif ti.Size == 64:
            if buf_size < 7:
                return -1
            string.strcpy(buf, "double")
            base_len = 6
        elif ti.Size == 128:
            if buf_size < 6:
                return -1
            string.strcpy(buf, "fp128")
            base_len = 5
        else:
            # 未知浮点尺寸 → double 兜底
            if buf_size < 7:
                return -1
            string.strcpy(buf, "double")
            base_len = 6
    else:
        # 整数: i{Size}，用 snprintf 安全写入
        if ti.Size <= 0:
            # 无效尺寸 → i8 兜底
            if buf_size < 4:
                return -1
            string.strcpy(buf, "i8")
            base_len = 2
        else:
            viperlib.snprintf(buf, buf_size, "i%d", ti.Size)
            base_len = string.strlen(buf)

    # 追加 PtrCount 个 "*"
    if base_len + ti.PtrCount + 1 > buf_size:
        return -1
    pos: int = base_len
    for i in range(ti.PtrCount):
        buf[pos] = '*'
        pos += 1
    buf[pos] = 0
    return pos


# ============================================================
# Mixin - 所有 Handle 的非多态基类（对应 TransPyC 的 BaseHandle）
#
# @t.NoVTable 继承：字段展平嵌入子类，无 vtable 开销（对应 C++ 非多态继承）。
# 子类继承 Trans 字段 + 共享工具方法，编译器自动生成子类方法包装
# （self bitcast 为父类指针后调用），子类可直接调用继承的方法。
#
# 用法：
#   @t.NoVTable
#   class AssignHandle(Mixin):
#       _CurrentClass: str
#       def __init__(self, trans):
#           self.InitMixin(trans)
#           self._CurrentClass = None
#       def Handle(self, node) -> int:
#           rhs = self.Trans.ExprH.HandleValue(node.value)
#           ...
# ============================================================
@t.NoVTable
class Mixin:
    """所有 Handle 的非多态基类：持有 Translator 回指针 + 共享委托方法"""
    Trans: HT.Translator | t.CPtr

    def InitMixin(self, trans: HT.Translator | t.CPtr) -> int:
        """初始化 Mixin 字段（子类 __init__ 中调用）"""
        self.Trans = trans
        return 0


# 全局 mbuddy 指针
_mbuddy: t.CVoid | t.CPtr
