# Released under the MIT License. See LICENSE for details.
#
"""Updates top level Makefile based on project elements present."""

from __future__ import annotations

import os
from typing import TYPE_CHECKING
import subprocess

if TYPE_CHECKING:
    pass


def generate_top_level_makefile(projroot: str, existing_data: str) -> str:
    """Main script entry point."""
    from efrotools import getconfig
    from pathlib import Path

    public = getconfig(Path(projroot))['public']
    assert isinstance(public, bool)

    original = existing_data
    lines = original.splitlines()

    auto_start = lines.index('# __AUTOGENERATED_DUMMY_MODULES_BEGIN__')
    auto_end = lines.index('# __AUTOGENERATED_DUMMY_MODULES_END__')

    our_lines = [
        _get_dummy_module_target(projroot),
    ]

    filtered = lines[: auto_start + 1] + our_lines + lines[auto_end:]
    out = '\n'.join(filtered) + '\n'

    return out


def _get_dummy_module_target(projroot: str) -> str:
    lines = (
        subprocess.run(
            [
                'find',
                os.path.join(projroot, 'src/ballistica'),
                '-name',
                'python_*',
            ],
            check=True,
            capture_output=True,
        )
        .stdout.decode()
        .splitlines()
    )
    targets: list[str] = []
    for line in lines:
        fname = os.path.split(line)[1]
        if (
            fname.startswith('python_class_')
            or fname.startswith('python_methods_')
        ) and (fname.endswith('.cc')):
            assert ' ' not in line
            assert line.startswith(projroot + '/')
            targets.append(line.removeprefix(projroot + '/'))

    # Keep our results deterministic.
    targets.sort()

    # Also require a built binary and compiled scripts for it to use.
    # UPDATE - scratch that. Now just trying to make it clear that
    # dummy-modules should not be generated as part of regular dependency
    # setups but rather in a dedicated pass.
    # targets.append('assets-cmake-scripts')
    # targets.append('cmake-binary')

    # Let's just use a single file for dependency tracking and regenerate
    # all dummy modules when it is dirty. There's basically no speed difference
    # regenerating all dummy-modules vs a single one so this keeps things
    # simple. It also lets us blow away any orphaned modules.
    dmstatepath = 'build/dummymodules/.dummy_modules_state'
    dmstatedir = os.path.dirname(dmstatepath)
    out = (
        '\n# Update dummy Python modules when source files contributing to'
        ' them change.\n'
        f'{dmstatepath}: \\\n'
    )
    assert targets
    out += ' \\\n'.join(f' {target}' for target in targets)

    assert ' ' not in dmstatedir
    out += (
        '\n'
        f'\t@tools/pcommand with_build_lock gen_dummy_modules_lock \\\n'
        f' rm -rf {dmstatedir} \\&\\& mkdir -p {dmstatedir} \\\n'
        ' \\&\\& ./tools/pcommand gen_dummy_modules \\\n'
        f' \\&\\& touch {dmstatepath}'
    )

    return out
