#!/usr/bin/perl -w

package Autorepo::Intersections;

use strict;
use warnings;
#use Getopt::Long;
use Source::Shared::CLI;
use Autorepo::Config;

our @ISA = qw/Source::Shared::CLI/;

my $dest_mode=0;
my $opt_sec_dest=0;
my $verbose=0;
$verbose=1 if $ENV{TERM}; # not to pollute cron mail

my @binlists;
my @srclists;

sub print_longopt {
    print "  intersection options:
	--dest dest mode even if AUTOREPO_MERGE_COMPONENTS found
	--srcdest also find src doubles in dest mode
";
}
our @LONGOPT=(
    'dest' => sub {$dest_mode=1},
    'srcdest' => sub {$opt_sec_dest=1},
    'src-dest' => sub {$opt_sec_dest=1},
    );

__PACKAGE__->new()->get_and_process_cli_options();

if ($CONFIG{'AUTOREPO_MERGE_COMPONENTS'} and !$dest_mode) {
    my @MERGE_ROOTS=split(/\s+/,$CONFIG{'AUTOREPO_MERGE_COMPONENTS'});
    push @binlists, map {$_.'/'.$AUTOREPO_BRANCH.'/files/list/bin.list'} @MERGE_ROOTS;
    push @srclists, map {$_.'/'.$AUTOREPO_BRANCH.'/files/list/src.list'} @MERGE_ROOTS;
} else {
    if (!$CONFIG{'AUTOREPO_PURGE_DESTPATH'} or $CONFIG{'AUTOREPO_PURGE_DESTPATH'} eq 'none') {
	print STDERR "binary intersections disabled (AUTOREPO_PURGE_DESTPATH not set) \n";
	exit;
    }
    push @binlists, 
	"$AUTOREPO_ROOT/files/list/bin.list",
	$CONFIG{'AUTOREPO_PURGE_DESTPATH'}.'/../list/bin.list';
    push @srclists, 
	"$AUTOREPO_ROOT/files/list/src.list",
	$CONFIG{'AUTOREPO_PURGE_DESTPATH'}.'/../list/src.list' if $opt_sec_dest;
}

if (grep {! -e $_} @binlists) {
    print "binary intersections disabled (list not found)\n";
    print "binlist=",join(' ',grep {! -e $_} @binlists);
    exit 1;
}

if (grep {! -e $_} @srclists) {
    print "source intersections disabled (list not found)\n";
    print "srclist=",join(' ',grep {! -e $_} @srclists);
    exit 1;
}

my (%binlist2hash,%srclist2hash);
my ($i,$j);
# over diagonal in matrix; do not need self intersections
for ($i=0; $i<$#binlists; $i++) {
    my $ihash=&__get_binhash($binlists[$i]);
    for ($j=$i+1; $j<=$#binlists; $j++) {
	#print "debug: $i $j ($#binlists) $binlists[$i] $binlists[$j]\n";
	my $jhash=&__get_binhash($binlists[$j]);
	my $intersection=&get_set_intersection($ihash,$jhash);
	&report_intersection('bin',$binlists[$i],$binlists[$j],$ihash,$jhash,$intersection) if @$intersection;
    }
}
for ($i=0; $i<$#srclists; $i++) {
    my $ihash=&__get_srchash_name2srpm($srclists[$i]);
    for ($j=$i+1; $j<=$#srclists; $j++) {
	#print "debug: $i $j ($#srclists) $srclists[$i] $srclists[$j]\n";
	my $jhash=&__get_srchash_name2srpm($srclists[$j]);
	my $intersection=&get_set_intersection($ihash,$jhash);
	&report_intersection('src',$srclists[$i],$srclists[$j],$ihash,$jhash,$intersection) if @$intersection;
    }
}

# TODO: print to a file
sub report_intersection {
    my ($type,$listi,$listj,$ihash,$jhash,$intersection)=@_;
    return unless @$intersection;
    print "==================================================================\n";
    print "Intersection: $type $listi, $listj\n";
    print "==================================================================\n";
    foreach my $element (@$intersection) {
	print "$element\t$ihash->{$element} $jhash->{$element}\n";
    }
    print "==================================================================\n";
}

sub __get_binhash {
    my ($list)=@_;
    my $hash=$binlist2hash{$list};
    return $hash if $hash;
    $hash=&__load_altlist($list,\&__load_altbinlist_fn);
    $binlist2hash{$list}=$hash;
    return $hash;
}

sub __get_srchash_name2srpm {
    my ($list)=@_;
    my $hash=$srclist2hash{$list};
    return $hash if $hash;
    $hash=&__load_altlist($list,\&__load_altsrclist_fn_srchash_name2srpm);
    $srclist2hash{$list}=$hash;
    return $hash;
}


sub __load_altlist {
    my ($list, $func)=@_;
    open (my $fn, '<', $list) or die "can't open file $list\n";
    my $ret=&$func($fn);
    close($fn);
    return $ret;
}

sub __load_altsrclist_fn_srchash_name2srpm {
    my ($fn)=@_;
    my %name2srpm;
    while (my $line=<$fn>) {
	chomp $line;
	my @list = split(/\s+/,$line);
	next if @list!=3;
	my ($name,$evr,$srpm)=@list;
	$name2srpm{$name}=$srpm;
    }
    return \%name2srpm;
}

sub __load_altbinlist_fn {
    my ($fn)=@_;
    my %name2srpm;
    while (my $line=<$fn>) {
	chomp $line;
	my @list = split(/\s+/,$line);
	next if @list!=5;
	my ($name,$evr,$arch,$rpm, $srpm)=@list;
	$name2srpm{$name}=$srpm;
    }
    return \%name2srpm;
}

sub get_set_intersection {
    my ($setref1,$setref2)=@_;
    my @intersection;
    foreach my $element1 (keys(%$setref1)) {
	push @intersection, $element1 if $setref2->{$element1};
    }
    return \@intersection;
}
