# Emscripten WebGPU port with optional Wagyu extensions


import os
import zlib
from typing import Dict, Optional


OPTIONS = {
    'wagyu': "Enable Wagyu extensions (default: false)",
}
_VALID_OPTION_VALUES = {
    'wagyu': {'true', 'false'},
}
_opts: Dict[str, Optional[str]] = {
    'wagyu': 'false',
}


def _get_base_dir():
    return os.path.dirname(os.path.realpath(__file__))


def _get_include_dir():
    return os.path.join(_get_base_dir(), 'include')


def _get_src_dir():
    return os.path.join(_get_base_dir(), 'src')


def _get_srcs():
    return [ _get_src_dir() + '/webgpu.c' ]

def _recurse_dir(path):
    for (dirpath, dirnames, filenames) in os.walk(path):
        for filename in filenames:
            yield os.path.join(dirpath, filename)


def _get_build_files():
    return sorted([
        __file__,
        *_get_srcs(),
        *_recurse_dir(_get_include_dir()),
    ])


# compiler

def _check_option(option, value, error_handler):
    if value not in _VALID_OPTION_VALUES[option]:
        error_handler(
            f'[{option}] can be {list(_VALID_OPTION_VALUES[option])}, got [{value}]'
        )
    return value


def handle_options(options, error_handler):
    for option, value in options.items():
        value = value.lower()
        _opts[option] = _check_option(option, value, error_handler)


def process_args(ports):
    args = ['-isystem', _get_include_dir()]
    return args


# linker

def _get_flags(settings):
    lib_name_suffix = ''
    flags = []
    return (lib_name_suffix, flags)


def _get_name(settings):
    hash_value = 0

    def add(x):
        nonlocal hash_value
        hash_value = zlib.adler32(x, hash_value)

    build_files = _get_build_files()
    for filename in build_files:
        add(open(filename, 'rb').read())

    (lib_name_suffix, _) = _get_flags(settings)
    return f'libwebgpu-{hash_value:08x}{lib_name_suffix}.a'


def clear(ports, settings, shared):
    shared.cache.erase_lib(_get_name(settings))


def get(ports, settings, shared):
    if settings.allowed_settings:
        return []

    def create(final):
        includes = [_get_include_dir()]
        (_, flags) = _get_flags(settings)
        flags += []
        ports.build_port(_get_src_dir(), final, 'webgpu', includes=includes, flags=flags, srcs=_get_srcs())

    lib_name = _get_name(settings)
    return [shared.cache.get_lib(lib_name, create, what='port')]


def linker_setup(ports, settings):
    if settings.USE_WEBGPU:
        raise Exception('webgpu-port is not compatible with deprecated Emscripten USE_WEBGPU option')

    src_dir = _get_src_dir()

    settings.JS_LIBRARIES += [ os.path.join(src_dir, 'library_webgpu_stubs.js') ]

    # Ensure the function gets exported
    settings.EXPORTED_FUNCTIONS += ['_wgpuWagyuGetCompiledVersion']

    if _opts['wagyu'] == 'true':
        settings.JS_LIBRARIES += [ os.path.join(src_dir, 'library_webgpu_wagyu_stubs.js') ]
