#!/usr/bin/env python3
"""

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


import click
import dhfortran.debhelper as dh
import dhfortran.cli as cli
import dhfortran.compilers as cmplrs
from os.path import basename


##
## Pkgconfig-file -specific interface for debhelper
##
class PkgconfFileHelper(dh.DhFortranHelper):

    def __init__(self, options):
        super().__init__(options, "fortran-pkgconf", "dh_fortran_pkgconf")

    def can_work_automatically(cmdline_files: list[str]) -> bool:
        """Called by Debhelper.process_and_move_files()
        Can we run automatically, without user configuration?

        If this is true, d.autogenerate_pkg_filelist() needs to be defined
        """
        return False

    def compute_dest(self, src_file, vendor=None, flavor=None):
        """Where does pkgconfig file go ? 
        Should be called by base DebHelper() to move files"""

    def process_file(self, pkg, filename, target_pkg, target_dest=None):
        cli.debug_print(
            f"process_file [pkgconf]  {filename=} {target_pkg=} {target_dest=}"
        )
        fmoddir = cmplrs.get_fmoddir(self.options.flavor, self.options.arch)
        flibdir = cmplrs.get_flibdir(self.options.flavor, self.options.arch)
        fc = self.options.flavor

        update = {"@FMODDIR@": fmoddir, "@FLIBDIR@": flibdir, "@FC@": fc}
        updated = set()

        pkgdir = f"{cmplrs.flibdir}/{self.options.flavor}/pkgconfig"
        newname = f"{target_pkg}/{pkgdir}/{basename(filename)}"

        with open(filename, "r") as f:
            lines = f.readlines()
        for i, line in enumerate(lines):
            for v in update:
                if v in line:
                    line[i] = line[i].replace(v, update[v])
                    updated.add(v)
        # Updating vars is more risky. Update only if subst not already done
        for i, line in enumerate(lines):
            if line.startswith("fmoddir="):
                if "{prefix}" in line and "@FMODDIR@" in updated:
                    continue
                lines[i] = f"fmoddir={fmoddir}"
            if line.startswith("flibdir="):
                if "{prefix}" in line and "@FLIBDIR@" in updated:
                    continue
                lines[i] = f"flibdir={flibdir}"
            if line.startswith("FC="):
                if "{prefix}" in line and "@FC@" in updated:
                    continue
                lines[i] = f"FC={fc}"

        self.install_dir(f"{target_pkg}/{pkgdir}")
        with open(newname, "w") as n:
            for line in lines:
                print(line, file=n, end="")


@click.command(
    context_settings=dict(
        ignore_unknown_options=False,
    )
)
@click.option("--fc", help="Fortran compiler flavor, eg. gfortran-15")
@click.argument("files", nargs=-1, type=click.UNPROCESSED)
@cli.debhelper_common_args
def dh_fortran_pkgconf(files, *args, **kwargs):
    """
    *dh_fortran_pkgconf* is a debhelper program that rewrites pkgconfig files and
    updates paths to FMODDIR and FLIBDIR to find the correct Fortran modules files
    and libraries for a given compiler.

    *dh_fortran_pkgconf* is expected to be automatically added using the debhelper
    "addon" <fortran> ie. either automatically, by build-depending on 
    'dh-sequence-fortran', or explicitly:

        dh $@ --with fortran

    <dh_fortran_pkgconf> Searches the debian/ directory for files 
    B<debian/pkg.fortran-pkgconf> which lists pkgconfig files to process, 
    with the same syntax as debhelper install files.

    OPTIONS
        --tmpdir=dir
        --sourcedir=dir

    Look in the specified directory for files to be installed. It will look in 
    tmpdir first (typically debian/tmp) then sourceddir (.).

    USAGE

    The source pkgconfig file will be read and any placeholders @FMODDIR@, 
    @FLIBDIR@ and @FC@ will be updated to the correct values. 
    If these are not found, relevant lines in the value section will be 
    updated (eg. fmoddir= lines).

    TODO

    (1) relative entries such as prefix defines may be broken by moving pc file
    (2) Insert fmoddir, flibdir if missing


    The fortran-pkgconf file syntax follows dh_install: pairs of sources 
    and optional target directories. If the target directory is absolute 
    (starts with a  '/'), this directory is used in the target package.
    If the target  does not absolute, it will be treated as a subdirectory 
    of the pkgconfig path.

    The rewritten pkgconfig files will by default be added to 
          /usr/lib/$multiarch/fortran/$compiler-flavor/pkgconfig
    (eg usr/lib/aarch64-linux-gnu/fortran/gfortran-15/pkgconfig/mypkg.pc )
    This can then be used in the PKG_CONFIG_PATH
    """

    cli.verbose_print(f"dh_fortran_pkgconf called with {kwargs}")
    fc = kwargs["fc"]
    flavor, arch = cmplrs.get_fc_flavor_arch(fc)
    kwargs.update(
        {
            "flavor": flavor,
            "arch": arch,
        }
    )
    d = PkgconfFileHelper(dh.build_options(**kwargs))
    seachdirs = [d.options.tmpdir, "."]
    d.process_and_move_files(seachdirs, *files)
    ...


if __name__ == "__main__":
    import pytest

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