"""Compile Nim libraries as Python Extension Modules.

If you want your namespace to coexist with your pthon code, name this ponim.nim
and then your import will look like `from ponim.nim import adder` and
`from ponim import subtractor`. There must be a way to smooth that out in the
__init__.py file somehow.

Note that the file must be in the included source code dir. Currently it is
easiest to just put this in with your python code.
"""

from os import listdir, mkdir
from os.path import join, expanduser
from setuptools import Extension
from shutil import copyfile, rmtree
from typing import Sequence, Dict, List
import subprocess
import sys
import pathlib


# class NimLib(TypedDict):
#     """Wrapper around a lib name and path for nim cdoe"""

#     name: str
#     path: str


def nythonize(nimbase: str, modules: Sequence[Dict[str, str]]) -> List[Extension]:
    """Compile a Nim library as a Python Extension Module.

    `nimbase` is the path to `nimbase.h` on your system, which is needed for 
    Python to compile gene Nim generated C code.


    This builds a set of Extenstions, which are then passed back to setuptools.
    """
    extensions = []
    # Create a top level working dir
    rmtree(join("build", "nim_build"), ignore_errors=True)
    pathlib.Path(join("build", "nim_build")).mkdir(parents=True)
    for module in modules:
        module_dir = join("build", "nim_build", f"{module['name']}_build")
        rmtree(module_dir, ignore_errors=True)
        mkdir(module_dir)
        subprocess.run(
            [
                "nim",
                "compileToC",
                "--compileOnly",
                "-d:release",
                "-d:ssl",
                "--app:lib",
                "--opt:speed",
                "--gc:markAndSweep",
                f"--nimcache:{module_dir}",
                module["path"],
            ],
            check=True,
            stderr=sys.stdout.buffer,
        )
        copyfile(
            nimbase, join(module_dir, "nimbase.h"),
        )
        sources = []
        for c_source_file in listdir(module_dir):
            if c_source_file.endswith(".c"):
                sources.append(join(module_dir, c_source_file))
        extensions.append(
            Extension(
                name=module["name"],
                sources=sources,
                extra_compile_args=[
                    "-flto",
                    "-ffast-math",
                    "-march=native",
                    "-mtune=native",
                    "-O3",
                    "-fno-ident",
                    "-fsingle-precision-constant",
                ],
                extra_link_args=["-s"],
                include_dirs=[module_dir],
            )
        )
    return extensions

[((40, 11, 40, 37), 'os.path.join', 'join', ({(40, 16, 40, 23): '"""build"""', (40, 25, 40, 36): '"""nim_build"""'}, {}), "('build', 'nim_build')", False, 'from os.path import join, expanduser\n'), ((43, 21, 43, 74), 'os.path.join', 'join', ({(43, 26, 43, 33): '"""build"""', (43, 35, 43, 46): '"""nim_build"""', (43, 48, 43, 73): 'f"""{module[\'name\']}_build"""'}, {}), '(\'build\', \'nim_build\', f"{module[\'name\']}_build")', False, 'from os.path import join, expanduser\n'), ((44, 8, 44, 46), 'shutil.rmtree', 'rmtree', (), '', False, 'from shutil import copyfile, rmtree\n'), ((45, 8, 45, 25), 'os.mkdir', 'mkdir', ({(45, 14, 45, 24): 'module_dir'}, {}), '(module_dir)', False, 'from os import listdir, mkdir\n'), ((46, 8, 61, 9), 'subprocess.run', 'subprocess.run', (), '', False, 'import subprocess\n'), ((66, 29, 66, 48), 'os.listdir', 'listdir', ({(66, 37, 66, 47): 'module_dir'}, {}), '(module_dir)', False, 'from os import listdir, mkdir\n'), ((63, 21, 63, 50), 'os.path.join', 'join', ({(63, 26, 63, 36): 'module_dir', (63, 38, 63, 49): '"""nimbase.h"""'}, {}), "(module_dir, 'nimbase.h')", False, 'from os.path import join, expanduser\n'), ((70, 12, 84, 13), 'setuptools.Extension', 'Extension', (), '', False, 'from setuptools import Extension\n'), ((41, 17, 41, 43), 'os.path.join', 'join', ({(41, 22, 41, 29): '"""build"""', (41, 31, 41, 42): '"""nim_build"""'}, {}), "('build', 'nim_build')", False, 'from os.path import join, expanduser\n'), ((68, 31, 68, 62), 'os.path.join', 'join', ({(68, 36, 68, 46): 'module_dir', (68, 48, 68, 61): 'c_source_file'}, {}), '(module_dir, c_source_file)', False, 'from os.path import join, expanduser\n')]