#!/usr/bin/perl -w

# dh_puredata_substvar: Generate variables ${puredata:Depends},
#     ${puredata:Recommends} and  ${puredata:Suggests}
#     for Pure Data Debian packages.
#
# This file is part of the dh-puredata Debian package

# Copyright (c) 2018, 2019  Rafael Laboissière <rafael@debian.org>
# Copyright (c) 2022 IOhannes m zmölnig <umlaeute@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <https://www.gnu.org/licenses/>.

=encoding utf8

=head1 NAME

dh_puredata_substvar - generate substitution variables for a Pd external package

=cut

use strict;
use Debian::Debhelper::Dh_Lib;
use Dpkg::Control::Info;
#use Dpkg::Version;
use File::Find::Rule;

init ();

# INTROSPECTABLE: CONFIG-FILES NONE

=head1 SYNOPSIS

B<dh_puredata_substvar> [S<I<debhelper options>>]

=head1 DESCRIPTION

B<dh_puredata_substvar> generates the substitution variables to help packaging
Pd-externals for Debian (and derivatives).

=head2 Substitution variables

=over 4

=item C<${puredata:Depends}>

Typically C<puredata-core> or C<puredata>.
If the binary package can be used by a Pd64 runtime, this will also contain C<puredata64-core>

=item C<${puredata:Recommends}>

=item C<${puredata:Suggests}>

=item C<${puredata:Provides}>

If the binary package C<pd-foo> can be used by a Pd64 runtime, this will contain C<pd64-foo>

=item C<${puredata:Version}>

The Pd version (actually the version of the 'puredata-dev' binary package) against which
this package is built.

Added in version 3.3.

=back

=head1 PACKAGE VERSION

=over 4

=item X-PureData-MinimumVersion

If a package requires a newer version of Pure Data, it can declare this
by adding C<X-PureData-MinimumVersion: E<lt>versionE<gt>> to the respective binary package stanza.

C<version> must be a valid version string, which can be used in a package relationship.

Added in version 3.3.

=back

=cut

sub get_installed_package_version($)
{
    my ($package_name) = @_;
    return `dpkg-query -W -f '\${Version}' $package_name 2>/dev/null`;
}

sub min_pkg_version {
        my ($control, $editor,) = @_;
        my $field = sprintf('X-%s-MinimumVersion', ucfirst $editor);
        my $customver = $control->{$field};

        #$customver = Dpkg::Version->new($customver);
        #if (!$customver->is_valid()) {
        #    error("Invalid $field: $customver");
        #}

        return $customver;
}


my %depends = ();

# calculate a proper value for a <cpu> part of the extension
my $deb_host_arch = dpkg_architecture_value("DEB_HOST_ARCH");
chomp (my $cpu=qx{/usr/share/puredata/debian/dekencpu ${deb_host_arch} 2>/dev/null});
if ($cpu eq "") {
    # if there's none (e.g. because the helper script doesn't exist),
    # fall back to some default
    $cpu = ${deb_host_arch};
}

my $substvars_optional="";
my $dpkg_version = get_installed_package_version("dpkg");
`dpkg --compare-versions $dpkg_version lt 1.21.8`;
$substvars_optional="?" if $?;

foreach my $package (@{$dh{DOPACKAGES}}) {
    my $control = Dpkg::Control::Info->new;
    my $dir = "debian/$package";
    my $pd_version = get_installed_package_version("puredata-dev");
    my @pd_files = File::Find::Rule->file()->name('*.pd')->in($dir);
    my @meta_files = File::Find::Rule->file()->name('*-meta.pd')->in($dir);
    my @single_files = File::Find::Rule->file()->name("*.linux-${cpu}-32.so", "*.pd_linux")->in($dir);
    my @double_files = File::Find::Rule->file()->name("*.linux-${cpu}-64.so")->in($dir);

    my $minver = min_pkg_version($control->get_pkg_by_name($package), 'PureData');

    delsubstvar ($package, 'puredata:Version');
    addsubstvar ($package, "puredata:Version${substvars_optional}", $pd_version);

    my $can_pd32 = 0;
    if (scalar @single_files > 0) {
        $can_pd32 = 1;
    }
    my $can_pd64 = 0;
    if (scalar @double_files > 0) {
        $can_pd64 = 1;
    }
    if (package_arch($package) eq 'all') {
        $can_pd32 = 1;
        $can_pd64 = 1;
    }
    if ($can_pd32 || $can_pd64) {;} else {
        if (scalar @pd_files > 0) {
            # platform independent (but arch:any)
            $can_pd32 = 1;
            $can_pd64 = 1;
        }
    }

    my @depends_pdOR = ();
    my @recommends_pdOR = ();

    my @depends_pd = ();
    my @recommends_pd = ();
    my @suggests_pd = ();
    my @provides_pd = ();

    if ($can_pd32) {
        if (${minver} ne "") {
            @depends_pdOR = (@depends_pdOR, "puredata-core (>= $minver)");
        } else {
            @depends_pdOR = (@depends_pdOR, "puredata-core");
        }
        @depends_pdOR = (@depends_pdOR, "pd");
        @recommends_pdOR = (@recommends_pdOR, "puredata");
        if (rindex($package, "pd64-", 0) == 0) {
            @provides_pd = (@provides_pd, "pd-" . substr($package, 5));
        }
        if (scalar @meta_files > 0) {
            @suggests_pd = (@suggests_pd, "pd-libdir");
        }
    }
    if ($can_pd64) {
        if (${minver} ne "") {
            @depends_pdOR = (@depends_pdOR, "puredata64-core (>= $minver)");
        } else {
            @depends_pdOR = (@depends_pdOR, "puredata64-core");
        }
        @depends_pdOR = (@depends_pdOR, "pd64");
        @recommends_pdOR = (@recommends_pdOR, "puredata64");
        if (rindex($package, "pd-", 0) == 0) {
            @provides_pd = (@provides_pd, "pd64-" . substr($package, 3));
        }
        if (scalar @meta_files > 0) {
            @suggests_pd = (@suggests_pd, "pd64-libdir");
        }
    }

    @depends_pd = (@depends_pd, join(' | ', @depends_pdOR));
    @recommends_pd = (@recommends_pd, join(' | ', @recommends_pdOR));

    # Depends:
    # + Pd (core)
    # - libraries used for abstractions ([declare]) ?
    delsubstvar ($package, 'puredata:Depends');
    addsubstvar ($package, 'puredata:Depends', join(' | ', @depends_pd));

    # Recommends:
    # + Pd (full stack)
    # - libraries used for abstractions ([declare])
    delsubstvar ($package, 'puredata:Recommends');
    addsubstvar ($package, 'puredata:Recommends', join(', ', @recommends_pd));

    # Suggests:
    # - libraries used for help-patches ([declare])
    # + pd-libdir if <pkgname>-meta.pd exists
    delsubstvar ($package, 'puredata:Suggests');
    addsubstvar ($package, 'puredata:Suggests', join(', ', @suggests_pd));

    # Provides:
    # + Pd32: 'pd-<library>'
    # + Pd64: 'pd64-<library>'
    delsubstvar ($package, 'puredata:Provides');
    addsubstvar ($package, 'puredata:Provides', join(', ', @provides_pd));
}

=head1 SEE ALSO

L<debhelper(7)>, L<dh(1)>

This program is meant to be used together with debhelper for Debian
packages derived from Pd externals packages.
It is recommended to enable it by adding the C<dh-sequence-puredata>
virtual package to C<Build-Depends>, C<Build-Depends-Arch> or
C<Build-Depends-Indep>.
This is equivalent to adding C<dh-puredata> to the same field and adding
C<--with=puredata> to the dh sequencer in debian/rules, except that only
-arch/-indep/profiled builds are affected.
This is also slightly more simple in the most common case.

=head1 AUTHOR

IOhannes m zmölnig <umlaeute@debian.org>

=cut

exit;
