package Config::Model::Dpkg::DependencyList;

use strict;
use warnings;
use Mouse;
use v5.20;
use Scalar::Util qw/weaken/;

use feature qw/postderef signatures/;
no warnings qw/experimental::postderef experimental::signatures/;

extends qw/Config::Model::ListId/ ;

sub sort_algorithm {
    # sort along dep names. ${foo} are sorted before regular packages
    return sub {
        # if one dep begins with '$', reverse the args of cmp call
        (substr($_[0],0,1) eq '$' xor substr($_[1],0,1) eq '$') ? $_[1]->fetch cmp $_[0]->fetch
            : $_[0]->fetch cmp $_[1]->fetch;
    };
}

sub check_debhelper_compat_presence ($self, $error, $warn, $apply_fix, $silent = 0) {
    return unless $self->element_name eq 'Build-Depends' ;
    foreach my $dep ($self->fetch_all_values(check => 'no')) {
        return if $dep =~ /^debhelper(-compat)?/;
    }

    if ($apply_fix) {
        # extract installed version of debhelper
        my $str = `/usr/bin/dpkg -l debhelper`;
        my ($current_compat_value) = ($str =~ /ii\s+debhelper\s+(\d+)/);
        $self->push(qq!debhelper-compat (= $current_compat_value)!);
        $self->grab(steps => '- debhelper-version', grab_non_available => 1)
            -> store ($current_compat_value);
    }
    else {
        push $warn->@*, "Missing debhelper-compat or debhelper dependency in "
            . $self->element_name
            . ". Applying fix will add a dependency on 'debhelper-compat'.";
        $self->inc_fixes;
    }
    return;
}

sub BUILD ($self, $) {
    return unless $self->element_name eq 'Build-Depends' ;
    weaken($self);
    $self->add_check_content( sub { $self->check_debhelper_compat_presence(@_);} );
}

1;

=head1 NAME

Config::Model::Dpkg::DependencyList - Debian dependency list utilities

=head1 SYNOPSIS

 # to be used in configuration model for Build-Depends
 'Build-Depends' => {
     type => 'list'
     class => 'Config::Model::Dpkg::DependencyList',
     cargo => { ... },
 },

=head1 DESCRIPTION

This class is derived from L<Config::Model::AnyId>. Its purpose is to
provides utilities to manage Debian dependency list.

=head1 Methods

=head2 sort_algorithms

Returns a sub to be used to sort Dependencies like L<wrap-and-sort>,
i.e. with debhelper variables (e.g. C<${misc:Depends}>) first and
regular packages after.

This method overrides L<Config::Model::ListId/sort_algorithms>.

=head2 check_debhelper_compat_presence

Checks if dependency list contains C<debhelper-compat> virtual package.

When called when applying fixes, this method pushes a new dependency like
C<debhelper-compat (= $current_compat_value)>.

=head1 AUTHOR

Dominique Dumont, dod@debian.org

=head1 SEE ALSO

L<Config::Model>,
L<Config::Model::AnyId>,
L<Config::Model::Dpkg::Dependency>,
