import t, c
from t import CInt, CPtr, CChar
import viperlib
import viperio
import stdlib
import memhub


def mpool_main() -> CInt:
    buf: bytes = stdlib.malloc(256)

    arena: bytes = stdlib.malloc(4096)
    with memhub.MemPool(arena, 4096) as pool:
        p1: bytes = pool.alloc(32)
        p2: bytes = pool.alloc(64)
        p3: bytes = pool.alloc(128)
        if p1 != None and p2 != None and p3 != None:
            viperlib.snprintf(buf, 256, "MPool bump: 3 allocs OK")
            print(buf)
        else:
            viperlib.snprintf(buf, 256, "MPool bump: alloc FAILED")
            print(buf)

        pool.reset()
        p4: bytes = pool.alloc(256)
        if p4 != None:
            viperlib.snprintf(buf, 256, "MPool bump: reset+alloc OK")
            print(buf)
        else:
            viperlib.snprintf(buf, 256, "MPool bump: reset+alloc FAILED")
            print(buf)

    stdlib.free(arena)

    arena2: bytes = stdlib.malloc(4096)
    with memhub.MemSlab(arena2, 4096, 64) as spool:
        b1: bytes = spool.alloc(64)
        b2: bytes = spool.alloc(64)
        b3: bytes = spool.alloc(64)
        if b1 != None and b2 != None and b3 != None:
            viperlib.snprintf(buf, 256, "MPool slab: 3 allocs OK")
            print(buf)
        else:
            viperlib.snprintf(buf, 256, "MPool slab: alloc FAILED")
            print(buf)

        spool.free(b2)
        b4: bytes = spool.alloc(64)
        if b4 != None:
            viperlib.snprintf(buf, 256, "MPool slab: free+realloc OK")
            print(buf)
        else:
            viperlib.snprintf(buf, 256, "MPool slab: free+realloc FAILED")
            print(buf)

    stdlib.free(arena2)

    arena3: bytes = stdlib.malloc(4096)
    hpool: memhub.MemPool | CPtr = memhub.MemPool(arena3, 4096)
    h1: bytes = hpool.alloc(32)
    h2: bytes = hpool.alloc(64)
    if h1 != None and h2 != None:
        viperlib.snprintf(buf, 256, "MPool manual: 2 allocs OK")
        print(buf)
    else:
        viperlib.snprintf(buf, 256, "MPool manual: alloc FAILED")
        print(buf)
    hpool.reset()
    h3: bytes = hpool.alloc(128)
    if h3 != None:
        viperlib.snprintf(buf, 256, "MPool manual: reset+alloc OK")
        print(buf)
    else:
        viperlib.snprintf(buf, 256, "MPool manual: reset+alloc FAILED")
        print(buf)

    stdlib.free(arena3)

    arena4: bytes = stdlib.malloc(4096)
    with memhub.MemPool(arena4, 4096) as bpool:
        wb: viperio.Buf | CPtr = bpool.alloc_buf(128)
        if wb.data != None:
            viperlib.snprintf(wb.cstr(), 128, "MPool alloc_buf: hello from Buf!")
            print(wb.cstr())
        else:
            viperlib.snprintf(buf, 256, "MPool alloc_buf: FAILED")
            print(buf)

    stdlib.free(arena4)
    stdlib.free(buf)
    return 0
