import t, c
from stdint import *
import posix
import memhub
import stdlib


# POSIX 路径最大长度
MAX_PATH_LEN: t.CDefine = 4096

# 模块级全局 MBuddy 指针（由用户在 main 中赋值初始化）
_mbuddy: memhub.MemBuddy | t.CPtr


# =============================================================================
# 文件/目录属性查询
# =============================================================================

def _stat(path: str) -> posix.Stat | t.CPtr:
    """调用 stat 并返回 Stat 结构体指针。失败返回 None。
    注意：Stat 结构体通过 _mbuddy 分配，调用者负责释放。"""
    st: posix.Stat = posix.Stat()
    result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
    if result != 0:
        return None
    return t.CPtr(c.Addr(st))


def exists(path: str) -> bool:
    """检查文件/目录是否存在"""
    result: INT = posix.access(path, posix.F_OK)
    if result == 0:
        return True
    return False


def isdir(path: str) -> bool:
    """检查路径是否为目录"""
    st: posix.Stat = posix.Stat()
    result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
    if result != 0:
        return False
    if posix.S_ISDIR(st.st_mode):
        return True
    return False


def isfile(path: str) -> bool:
    """检查路径是否为普通文件"""
    st: posix.Stat = posix.Stat()
    result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
    if result != 0:
        return False
    if posix.S_ISREG(st.st_mode):
        return True
    return False


def getsize(path: str) -> t.CInt64T:
    """返回文件大小（字节）。失败返回 -1。"""
    st: posix.Stat = posix.Stat()
    result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
    if result != 0:
        return -1
    return st.st_size


# =============================================================================
# 工作目录
# =============================================================================

def getcwd_impl() -> str:
    """返回当前工作目录（通过 _mbuddy 分配内存）"""
    buf: bytes = _mbuddy.alloc(MAX_PATH_LEN)
    if buf == None: return None
    result: CHARPTR = posix.getcwd(buf, MAX_PATH_LEN)
    if result == None:
        return None
    return str(buf)


def chdir_impl(path: str) -> int:
    """切换当前工作目录。成功返回 0，失败返回 -1。"""
    result: INT = posix.chdir(path)
    if result != 0:
        return -1
    return 0


# =============================================================================
# 文件/目录操作
# =============================================================================

def mkdir_impl(path: str) -> int:
    """创建目录。成功返回 0，失败返回 -1。
    默认权限 0o755（rwxr-xr-x）。"""
    result: INT = posix.mkdir(path, 0o755)
    if result != 0:
        return -1
    return 0


def remove(path: str) -> int:
    """删除文件。成功返回 0，失败返回 -1。"""
    result: INT = posix.unlink(path)
    if result != 0:
        return -1
    return 0


def rmdir_impl(path: str) -> int:
    """删除空目录。成功返回 0，失败返回 -1。"""
    result: INT = posix.rmdir(path)
    if result != 0:
        return -1
    return 0


def rename_impl(old_path: str, new_path: str) -> int:
    """重命名/移动文件或目录。成功返回 0，失败返回 -1。"""
    result: INT = posix.rename(old_path, new_path)
    if result != 0:
        return -1
    return 0


def chmod_impl(path: str, mode: int) -> int:
    """修改文件权限。成功返回 0，失败返回 -1。
    mode 为 POSIX 权限位（如 0o755）。"""
    result: INT = posix.chmod(path, posix.mode_t(mode))
    if result != 0:
        return -1
    return 0


# =============================================================================
# 目录列举（opendir / readdir / closedir）
# =============================================================================

def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
    """列举目录下的文件/子目录名。
    out_names 为调用者提供的字符串指针数组（char**），每个元素指向一个文件名。
    文件名通过 _mbuddy 分配内存。
    max_count 为 out_names 数组最大容量。
    返回实际列举的条目数。失败返回 0。"""
    dirp: posix.DIR | t.CPtr = posix.opendir(path)
    if dirp == None:
        return 0

    count: ULONG = 0
    while count < max_count:
        entry: posix.Dirent | t.CPtr = posix.readdir(dirp)
        if entry == None:
            break

        # 读取 d_name 字段
        name: str = entry.d_name
        if name[0] == '.':
            if name[1] == 0:
                # "."
                continue
            if name[1] == '.' and name[2] == 0:
                # ".."
                continue

        # 复制文件名到新分配的内存
        name_len: t.CSizeT = len(name)
        name_buf: bytes = _mbuddy.alloc(name_len + 1)
        if name_buf == None: break
        i: t.CSizeT = 0
        for ch in name:
            name_buf[i] = ch
            i += 1
        name_buf[name_len] = 0
        out_names[count] = str(name_buf)
        count += 1

    posix.closedir(dirp)
    return count


# =============================================================================
# 命令执行
# =============================================================================

def system_impl(cmd: str) -> int:
    """执行命令行命令（通过 C 运行时 system()）。
    命令输出直接到子进程的终端（继承父进程 stdout/stderr）。
    返回命令的退出码（0 表示成功）。"""
    return stdlib.system(cmd)
