#!/usr/bin/python3
"""
Driver for dh-fortran d/rules targets

Copyright (C) 2025 Alastair McKinstry <mckinstry@debian.org>
Released under the GPL-3 GNU Public License.
"""

import os
import subprocess
import sys
from functools import wraps
import dhfortran.cli as cli
import dhfortran.compilers as cmplrs


def set_env(flavor):
    """Set Fortran env"""
    env = (
        subprocess.check_output(["dh_fortran", "get_env", "--fc", flavor])
        .strip()
        .decode("utf-8")
    )
    for line in env.split('\n'):
        key, val = line[: line.find("=")], line[line.find("=") + 1 :]
        os.environ[key] = val



def doit(args, verbose=False):
    if verbose and "DH_VERBOSE" in os.environ:
        args += ["--verbose"]
    cli.verbose_print(args)
    subprocess.run(args, stdout=sys.stdout, stderr=sys.stderr)


def foreach_compiler(fail_on_error_on_default=True):

    def outer(f):
        @wraps(f)
        def inner(*args, **kwargs):
            try:
                for flavor in cmplrs.get_fc_required():
                    cli.verbose_print(f"   {f.__name__} {flavor} ")
                    f(flavor=flavor, **kwargs)
            except Exception as ex:
                cli.verbose_print(f"FAIL: {f.__name__} : error {ex}")
                if fail_on_error_on_default:
                    raise
            for flavor in cmplrs.get_fc_optional():
                 try:
                     cli.verbose_print(f"   {f.__name__} {flavor} ")
                     f(flavor=flavor,  **kwargs)
                 except Exception as ex:
                     cli.verbose_print(f"{f.__name__}: ignoring error {ex}"
                                       "(testing optional compiler")
        return inner

    return outer


@foreach_compiler(fail_on_error_on_default=False)
def dh_fortran_clean(flavor,  **kwargs):
    if kwargs['builddir'] not in {None, '.'}:
            doit(["rm", "-rf", f"{kwargs['builddir']}-{flavor}"])
    if 'tmpdir' in kwargs and kwargs['tmpdir'] is not None:
        doit(["rm", "-rf", f"{kwargs['tmpdir']}-{flavor}"])


@foreach_compiler(fail_on_error_on_default=False)
def dh_fortran_install(flavor: str, **kwargs):
    """Do Fortran-specific operations on d/rules install target"""
    set_env(flavor)
    if kwargs['destdir'] is not None:
        destdir = kwargs["destdir"]
    else:
        destdir = f"{kwargs['tmpdir']}-{flavor}"
        
    # TODO If flavor = FC_DEFAULT, set a symlink for tmpdir
    if kwargs['buildsystem'] == 'fortran':
        doit(["fpm", "install", f"--prefix={destdir}/usr"],verbose=True)
    # Execute these with tmpdir set; paths in config files may be
    # relative to tmpdir
    doit(["dh_fortran_mod", f"--tmpdir={destdir}"])
    doit(["dh_fortran_lib", f"--tmpdir={destdir}",f"--fc={flavor}"])
    doit(["dh_fortran_pkgconf", f"--tmpdir={destdir}",f"--fc={flavor}"])
    doit(["dh_fortran_cmake", f"--tmpdir={destdir}",f"--fc={flavor}"])        

@foreach_compiler()
def dh_install_on_cmake_makefile(flavor: str, **kwargs):
    """ On cmake+makefile, for each Fortran-build,
    jump in and do make install with overridden destdir """
    builddir= f"{kwargs['builddir']}-{flavor}"
    if kwargs['destdir'] is not None:
        destdir = kwargs["destdir"]
    else:
        destdir = f"{kwargs['tmpdir']}-{flavor}"
    dest = f"{os.getcwd()}/{destdir}"
    doit(["make","-C", builddir,"install",f"DESTDIR={dest}"])
    doit(["dh_fortran_mod", f"--tmpdir={dest}"])
    doit(["dh_fortran_lib", f"--tmpdir={dest}",f"--fc={flavor}"])
    doit(["dh_fortran_pkgconf", f"--tmpdir={dest}"])
    doit(["dh_fortran_cmake", f"--tmpdir={dest}"])        
    

@foreach_compiler(fail_on_error_on_default=False)
def dh_fortran_configure(flavor: str, **kwargs):
    """Do Fortran-specific operations on d/rules configure target"""
    # FPM does not have a configure target
    pass


@foreach_compiler(fail_on_error_on_default=False)
def dh_fortran_build(flavor: str, **kwargs):
    """Do Fortran-specific operations on d/rules build target"""
    if kwargs['buildsystem'] == 'fortran':
        set_env(flavor)
        doit(["fpm", "build"],verbose=True)


@foreach_compiler()
def dh_fortran_test(flavor: str, **kwargs):
    """Do Fortran-specific operations on d/rules test target"""
    if kwargs['buildsystem'] == 'fortran':
        set_env(flavor)
        doit(["fpm", "test"])

if __name__ == "__main__":
    import pytest

    pytest.main(["tests/targets.py"])
