#!/usr/bin/perl -w

use strict;

use Debian::Debhelper::Dh_Lib;
use Digest::MD5;
use Dpkg::Control;
use File::Find;

init();

umask 0022;

my $md5dir = "/var/lib/coq/md5sums";
my $md5ext = ".checksum";

sub is_coqpackage
{
    ($_) = @_;
    if (/^libcoq(.*)-ocaml-dev$/) {
	return 0;
    };
    if (/^libcoq(.*)-ocaml$/) {
	return 0;
    };
    if (/^libcoq(.*)$/) {
	return 1;
    };
    return 0;
};

sub compute_checksum
{
    my ($filelist) = @_; 
    my $ctx = Digest::MD5->new;
    open FL, $filelist;
    foreach (<FL>)
    {
	open FH, $_;
	$ctx->addfile(*FH);
    };
    my $hash = $ctx->hexdigest();
    # now we do like in ocaml-md5sums: some base 36 encoding of the first digits,
    # so it's shorter
    my $sig = hex(substr($hash, 0, 6));
    my $digit;
    my @accu;
    for (my $i = 0; $i < 5; $i++)
    {
	$digit = $sig % 36;
	$sig = $sig / 36;
	push(@accu, (chr ($digit + ($digit < 10 ? (ord '0') : ((ord 'a')-10)))));
    };
    return join "", @accu;
};

verbose_print "Detect Coq packages";
my @coq_packages;
foreach (@{$dh{DOPACKAGES}}) {
    if (is_coqpackage($_)) {
	push(@coq_packages, $_);
    };
};

verbose_print "Compute the list of their .vo files";
my %volist;
foreach my $package (@coq_packages)
{
    my $volist_fn = "debian/".(pkgext $package)."volist.debhelper";
    $volist{$package} = $volist_fn;
    # remove existing file we could have built
    if ($volist_fn)
    {
	verbose_print("\tfirst remove previous $volist_fn");
	unlink $volist_fn unless $dh{NO_ACT};
    };
    # if developer provided a volist file, use that
    if (pkgfile($package, "volist"))
    {
	if (!$dh{NO_ACT})
	{
	    open(FIN, "<", pkgfile($package, "volist"));
	    open(FOUT, ">", $volist_fn);
	    foreach (<FIN>)
	    {
		print FOUT (tmpdir $package)."/$_\n";
	    };
	    close(FIN);
	    close(FOUT);
	};
    }
    else # no list provided, autodetect
    {
	if (!$dh{NO_ACT})
	{
	    my @search_path = tmpdir $package;
	    open(VOLIST, ">", $volist_fn);
	    find {
		'wanted' => sub { (-f $_) && (/\.vo$/)
				      && (print VOLIST $File::Find::name."\n") }
	    }, @search_path;
	    close(VOLIST);
	    doit('cat', $volist_fn) if $dh{VERBOSE};
	};
    };
}

verbose_print "Compute the checksums of the coq packages";
my %checksums;
foreach my $package (@coq_packages)
{
    my $md5sum_fn = (tmpdir $package)."/$md5dir/$package$md5ext";
    doit(qw/mkdir -p/, dirname $md5sum_fn);
    my $checksum = compute_checksum($volist{$package});
    open FH, ">", $md5sum_fn;
    print FH $checksum;
    $checksums{$package} = $checksum;
};

verbose_print "Compute coq:Depends' value";
my @deps;
my $control = Dpkg::Control->new(type => CTRL_INFO_SRC);
if ($control->load('debian/control'))
{
    for my $field (grep /^Build-Depends/, keys %{$control})
    {
	my $builddeps = $control->{$field};
	while ($builddeps =~ /([-a-z]*)(?:[,\(])/g)
	{
	    my $dep = $1;
	    if (is_coqpackage($dep))
	    {
		verbose_print $dep;
		if (-f "$md5dir/$dep$md5ext")
		{
		    open CK, "$md5dir/$dep$md5ext";
		    my $checksum = <CK>;
		    push @deps, "$dep-$checksum";
		}
		else
		{
		    push @deps, $dep;
		}
	    };
	};
    };
};
my $deps = join(', ', @deps);

verbose_print "Export the subsvars";
foreach my $package (@coq_packages)
{
    delsubstvar $package, "coq:Provides";
    delsubstvar $package, "coq:Depends";
    addsubstvar $package, "coq:Provides", "$package-".$checksums{$package};
    addsubstvar $package, "coq:Depends", "$deps";
};
