from typing import Callable
from packaging.version import Version

# 项目常量
PROJECT_PATH: str = ''
BUILD_DIR: str = ''
GITHUB_ACTIONS: bool = False
BUILD_TYPE: str = 'release'

CC: str = ''
CXX: str = ''
CC_TYPE: str = 'unknown'
CC_VERSION: Version = Version('0.0.0')
CXX_TYPE: str = 'unknown'
CXX_VERSION: Version = Version('0.0.0')

AS: str = ''  # 汇编器
NASM: str = ''
AR: str = ''  # 打包器
LINKER: str = ''  # 链接器

# 编译参数
INCLUDE_FILES: list[str] = []
INCLUDE_FILES_C: list[str] = []
INCLUDE_FILES_CPP: list[str] = []

INCLUDE_DIRS: list[str] = []
INCLUDE_DIRS_C: list[str] = []
INCLUDE_DIRS_CPP: list[str] = []

LIB_DIRS: list[str] = []

COMPILE_FLAGS_POSTFIX: str = ''
LINK_FLAGS_POSTFIX: str = ''

COMPILE_FLAGS: str = ''
COMPILE_FLAGS_C: str = ''
COMPILE_FLAGS_CPP: str = ''
COMPILE_FLAGS_ASM: str = ''
COMPILE_FLAGS_NASM: str = ''

FLAGS_OVERWRITE_C: bool = False
FLAGS_OVERWRITE_CPP: bool = False
FLAGS_OVERWRITE_ASM: bool = False
FLAGS_OVERWRITE_NASM: bool = True

LINK_FLAGS: str = ''

# 每个文件不同的常量
DIR: str = ''
FILE: str = ''


# 日志
def fatal(message: str, rets: int = 1, e: Exception | None = None):
  '''
    message: 日志信息
    rets: 返回值
    e: 异常
  '''
  ...


def error(message: str, rets: int | None = None, e: Exception | None = None):
  '''
    message: 日志信息
    rets: 返回值
    e: 异常
  '''
  ...


def warn(message: str, e: Exception | None = None):
  '''
    message: 日志信息
    e: 异常
  '''
  ...


def info(message: str):
  '''
    message: 日志信息
  '''
  ...


def debug(message: str):
  '''
    message: 日志信息
  '''
  ...


def find_files(dir: str, pattern: str) -> list[str]:
  ...


def abspath(path: str) -> str:
  ...


def relpath(path: str, start: str | None = None) -> str:
  ...


# 生成一个头文件
def mkheader(name: str, srcdir: str | None = None, workdir: str | None = None, recurse: bool = False, flag: str = 'h') -> int:
  """
    flag:
      h: 生成一个 .h 文件
      hpp: 生成一个 .hpp 文件
      h-only: 生成一个 .h 文件，但不包含 .hpp 文件
      hpp-only: 生成一个 .hpp 文件，但不包含 .h 文件
  """
  ...


# 源代码目录
def src_dir(*dirs: str, hidden_file: bool = False):
  ...


# 编译一个源代码文件
def compile(*files: str, exclude: list[str] | str | None = None, flags_overwrite: str | list[str] | None = None) -> str:
  '''
    编译源代码并链接
    files: 源代码文件
    flags_overwrite: 覆盖编译参数
      -> 输出文件路径
  '''
  ...


def link(*, flags_overwrite: str | list[str] | None = None) -> str:
  '''
    链接目标
    flags_overwrite: 覆盖链接参数
      -> 输出文件路径
  '''
  ...


def include(*files: str, lang: str = 'all', abslute: bool = False):
  '''
    files: 头文件
    lang: 语言类型 ['all', 'c', 'cpp', 'asm']
    abslute: 是否使用绝对路径
  '''
  ...


def include_dir(*dir: str, lang: str = 'all'):
  '''
    dir: 头文件目录
    lang: 语言类型 ['all', 'c', 'cpp', 'asm']
  '''
  ...


def depedency(*targets: str, type: str = 'any'):
  '''
    targets: 依赖的目标
    type: 依赖类型 ['any', 'static', 'dynamic']
      any: 任何类型
      static: 静态库
      dynamic: 动态库
  '''
  ...


def lib_dir(*dir: str):
  ...


def clear_compile_flags(lang: str = 'all') -> None:
  ...


def add_compile_flags(*flags: str, lang: str = 'all') -> None:
  ...


def remove_compile_flags(*flags: str, lang: str = 'all') -> None:
  ...


def clear_link_flags() -> None:
  ...


def add_link_flags(*flags: str) -> None:
  ...


def remove_link_flags(*flags: str) -> None:
  ...


def target(name: str, type: str = 'exec', platforms: list[str] | str | None = None) -> Callable[[Callable], Callable]:
  '''
    name: 目标名称
    type: 目标类型 ['exec', 'static-exec', 'lib', 'static-lib', 'dynamic-lib', 'customize']
  '''
  ...


def platform(name: str) -> Callable[[Callable], Callable]:
  '''
    name: 平台名称
  '''
  ...


# 编译过程
def before_build(target: str) -> Callable[[Callable], Callable]:
  '''
    在构建目标之前执行
    target: 目标名称
  '''
  ...


def before_compile(target: str) -> Callable[[Callable], Callable]:
  '''
    在每个源文件编译之前执行
    target: 目标名称
  '''
  ...


def after_compile(target: str) -> Callable[[Callable], Callable]:
  '''
    在每个源文件编译之后执行
    target: 目标名称
  '''
  ...


def before_link(target: str) -> Callable[[Callable], Callable]:
  '''
    在链接目标之前执行
    target
  '''
  ...


def after_link(target: str) -> Callable[[Callable], Callable]:
  '''
    在链接目标之后执行
    target
  '''
  ...


def after_build(target: str) -> Callable[[Callable], Callable]:
  '''
    在构建目标之后执行
    target
  '''
  ...


def dump_flags():
  ...


def system(*cmd: str, cwd: str | None = None, env: dict[str, str] | None = None) -> bool:
  ...


# def on_clean(target: str) -> Callable[[Callable], Callable]:
#   '''
#     在清理目标之前执行
#     target: 目标名称
#   '''


class CCommentReader:
  ...


class CFileFlagReader:
  ...


class CFileGenerator:
  ...
