import t
import stdio
import testcheck
import stdlib
import memhub
import string
from linkedlist import GSListNode, GSList


# ============================================================
# G5: 验证 GSList[T] 被降级为 opaque 的问题
#
# 版本 2: 不使用 malloc/MemBuddy，直接用构造函数（像 G3 那样）
# 这样能隔离 GSList opaque 问题
# ============================================================


# G5Node: 继承 GSListNode[G5Node]（Phase2 路径，正确特化）
@t.NoVTable
class G5Node(GSListNode[G5Node]):
    Value: t.CInt

    def __init__(self):
        self.Next = None
        self.Value = 0


# G5ListWrapper: 包装 GSList[G5Node]，测试 GSList 字段访问
# 注意：GSList[G5Node] 走 Phase2 特化路径
# 用 pool 工厂函数分配 GSList，避免栈分配悬垂指针
GSLIST_SIZE: t.CDefine = 24  # Head(8) + Tail(8) + Count(8)

@t.NoVTable
class G5ListWrapper:
    List: GSList[G5Node] | t.CPtr

    def __init__(self, pool: memhub.MemBuddy | t.CPtr):
        gsl: GSList[G5Node] | t.CPtr = pool.alloc(GSLIST_SIZE)
        if gsl is None:
            self.List = None
            return
        string.memset(gsl, 0, GSLIST_SIZE)
        self.List = gsl


# ============================================================
# Test 1: G5Node 字段访问（基准测试，应通过）
# ============================================================

def test_g5node_create():
    testcheck.section("Test 1: G5Node create and field access")
    n: G5Node = G5Node()
    n.Value = 42
    v: t.CInt = n.Value
    testcheck.check(v == 42, "G5Node.Value = 42", "expect 42")


def test_g5node_next():
    testcheck.section("Test 2: G5Node.Next field (GSListNode inheritance)")
    n1: G5Node = G5Node()
    n2: G5Node = G5Node()
    n1.Value = 10
    n2.Value = 20
    n1.Next = n2
    next_node: G5Node = n1.Next
    if next_node is None:
        testcheck.check(False, "n1.Next is None", "FAIL")
        return
    v: t.CInt = next_node.Value
    testcheck.check(v == 20, "n1.Next.Value = 20", "expect 20")


# ============================================================
# Test 3: GSList 字段访问 — 核心测试
# ============================================================

def test_gslist_create():
    testcheck.section("Test 3: GSList[G5Node] create")
    lst: GSList[G5Node] | t.CPtr = GSList[G5Node]()
    if lst is None:
        testcheck.check(False, "GSList[G5Node]() is None", "FAIL")
        return
    # 检查初始状态
    head: G5Node | t.CPtr = lst.Head
    tail: G5Node | t.CPtr = lst.Tail
    count: t.CSizeT = lst.Count
    testcheck.check(head is None, "initial Head is None", "expect None")
    testcheck.check(tail is None, "initial Tail is None", "expect None")
    testcheck.check(count == 0, "initial Count = 0", "expect 0")


def test_gslist_append():
    testcheck.section("Test 4: GSList[G5Node].append 3 nodes")
    lst: GSList[G5Node] | t.CPtr = GSList[G5Node]()
    if lst is None:
        testcheck.check(False, "GSList[G5Node]() is None", "FAIL")
        return
    a: G5Node = G5Node()
    b: G5Node = G5Node()
    c: G5Node = G5Node()
    a.Value = 1
    b.Value = 2
    c.Value = 3

    lst.append(a)
    lst.append(b)
    lst.append(c)

    # 验证 Count
    count: t.CSizeT = lst.Count
    testcheck.check(count == 3, "Count = 3 after 3 appends", "expect 3")

    # 验证 Head
    head: G5Node | t.CPtr = lst.Head
    if head is None:
        testcheck.check(False, "Head is None", "FAIL")
        return
    testcheck.check(head.Value == 1, "Head.Value = 1", "expect 1")

    # 验证 Tail
    tail: G5Node | t.CPtr = lst.Tail
    if tail is None:
        testcheck.check(False, "Tail is None", "FAIL")
        return
    testcheck.check(tail.Value == 3, "Tail.Value = 3", "expect 3")

    # 遍历链表验证顺序
    sum: t.CInt = 0
    cur: G5Node | t.CPtr = lst.Head
    while cur is not None:
        sum = sum + cur.Value
        cur = cur.Next
    testcheck.check(sum == 6, "chain sum = 1+2+3 = 6", "expect 6")


# ============================================================
# Test 5: G5ListWrapper.List 字段访问（嵌套 GSList 测试）
# ============================================================

def test_wrapper_list_field():
    testcheck.section("Test 5: G5ListWrapper.List field (nested GSList, pool alloc)")
    arena: bytes = stdlib.malloc(4096)
    if arena is None:
        testcheck.check(False, "malloc arena", "FAIL")
        return
    pool: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, 4096)
    wrapper: G5ListWrapper = G5ListWrapper(pool)
    if wrapper is None:
        testcheck.check(False, "G5ListWrapper(pool) is None", "FAIL")
        return
    if wrapper.List is None:
        testcheck.check(False, "wrapper.List is None", "FAIL")
        return

    n: G5Node = G5Node()
    n.Value = 999
    wrapper.List.append(n)

    # 通过 wrapper.List 访问 GSList 字段
    head: G5Node | t.CPtr = wrapper.List.Head
    if head is None:
        testcheck.check(False, "wrapper.List.Head is None", "FAIL")
        return
    count: t.CSizeT = wrapper.List.Count
    testcheck.check(head.Value == 999, "wrapper.List.Head.Value = 999", "expect 999")
    testcheck.check(count == 1, "wrapper.List.Count = 1", "expect 1")


def main() -> t.CInt:
    testcheck.begin("G5: GSList[T] field access (Phase2 path, pool alloc for wrapper)")
    test_g5node_create()
    test_g5node_next()
    test_gslist_create()
    test_gslist_append()
    test_wrapper_list_field()
    return testcheck.end()
