#!/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,exists


##
## 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(self, *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, target_pkg, target_dest=None) -> str:
        """Where does pkgconfig file go ?
        Should be called by base DebHelper() to move files"""
        cli.debug_print(f"compute_dest [pkgconf]  {src_file=} {target_dest=}")
        pkgdir = f"debian/{target_pkg}/usr/lib/{cmplrs.multiarch}/pkgconfig"

        if target_dest is None or target_dest=='':
            return pkgdir
        if target_dest.startswith("/"):
            return target_dest
        else:
            return f"{pkgdir}/{target_dest}"
        
        
        
        
    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,
                  "@DEB_HOST_MULTIARCH@" : cmplrs.multiarch}
        updated = set()
        
        destdir=f"{self.compute_dest(filename, target_pkg, target_dest)}"
        b = basename(filename)
        root = b[:b.rfind('.pc')]
        abi = cmplrs.get_abi_vendor(flavor=cmplrs.get_fc_flavor_arch(fc)[0])
        destfile = f"{destdir}/{root}-{fc}.pc"
        if exists(destfile):
            if self.options.flavor == self.options.preferred:
                cli.verbose_print(f"{destfile} exists but will be overwritten"
                "(preferred)")
            else:
                cli.verbose_print(f"{destfile} exists and will not be overwritten")
                return            
                
        with open(filename, "r") as f:
            lines = f.readlines()
        for i, line in enumerate(lines):
            for v in update:
                lines[i] = lines[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}\n"
            if line.startswith("flibdir="):
                if "{prefix}" in line and "@FLIBDIR@" in updated:
                    continue
                lines[i] = f"flibdir={flibdir}\n"
            if line.startswith("FC="):
                if "{prefix}" in line and "@FC@" in updated:
                    continue
                lines[i] = f"FC={fc}"

        dh.install_dir(destdir)
        cli.verbose_print(f"dh_fortran_pkgconf: creating {destfile}")
        with open(destfile, "w") as n:
            for line in lines:
                print(line, file=n, end="")
        # symlinks
        dh.install_dir(f"debian/{target_pkg}{flibdir}/pkgconfig")
        dh.make_symlink(f"debian/{target_pkg}{flibdir}/pkgconfig/{root}.pc",
                        destfile,
                        target_dest)
        if self.options.flavor == self.options.preferred:            
            dh.make_symlink(f"{destdir}/{root}.pc",
                            destfile,
                            target_dest)
            

@click.command(
    context_settings=dict(
        ignore_unknown_options=False,
    )
)
@click.option("--fc", help="Fortran compiler flavor, eg. gfortran-15")
@click.option(
    "--preferred", help="Preferred compiler flavor when installing, 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.debug_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,
            "preferred": cmplrs.get_preferred(kwargs["preferred"], flavor),
        }
    )
    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"])
