#!/usr/bin/perl
#
# Author:  Petter Reinholdtsen
# Date:    2006-02-21
# License: GNU Public License v2
#
# Compare two memberlist files, and print a summary of the changes
# between them.
use strict;
use warnings;

BEGIN {
    # Add script location to include path
    my @p = split(m%/%, $0); pop @p; push @INC, join("/", @p);
}

use Getopt::Std;
use medlemsliste;

my %oldmembers;
my %newmembers;
my %memberids;

my %opts;
getopts("df:p:r", \%opts);
my $debug = $opts{d};

load_memberslist($opts{f} || "medlemsliste.csv",
		 \&process_entry, \%newmembers);
load_memberslist($opts{p} || "medlemsliste-old.csv",
		 \&process_entry, \%oldmembers);

my @gain;
my @loss;
my @changed;
my @removed;
my @emailchanged;
my @addrchanged;
for my $id (sort keys %memberids) {
    my @msgs;
    if (!exists $oldmembers{$id}) {
	# New entry exist, old entry missing
	if ($newmembers{$id}->{'ZUsrMedlemstatus'}) {
	    push @gain, $id;
	}
    } elsif (!exists $newmembers{$id}) { # Old entry exist, new entry missing
	push @removed, $id;
	if ($oldmembers{$id}->{'ZUsrMedlemstatus'}) {
	    push @loss, $id;
	}
    } else {
	# Both new and old entry exist
	if ($oldmembers{$id}->{'ZUsrMedlemstatus'} ne
	    $newmembers{$id}->{'ZUsrMedlemstatus'}) {
	    if ($oldmembers{$id}->{'ZUsrMedlemstatus'} and
		!$newmembers{$id}->{'ZUsrMedlemstatus'}) {
	        push @loss, $id;
	    } elsif ($newmembers{$id}->{'ZUsrMedlemstatus'} and
		!$oldmembers{$id}->{'ZUsrMedlemstatus'}) {
	        push @gain, $id;
	    } else {
	        push @changed, $id;
	    }
	}

	if ($oldmembers{$id}->{'EmailAddress'} ne
	    $newmembers{$id}->{'EmailAddress'}) {
	    push @emailchanged, $id;
	}

	my $oldaddr = addr_string($oldmembers{$id});
	my $newaddr = addr_string($newmembers{$id});
	if ($oldaddr ne $newaddr) {
	    push @addrchanged, $id;
	}
    }
}

if ($opts{'r'}) { # List address of removed members
    for my $id (sort oldnamesort @loss) {
        next if ("FIRMAMEDLEM" eq $oldmembers{$id}->{ZUsrMedlemstatus});

        my $address = $newmembers{$id}->{EmailAddress} ||
                      $oldmembers{$id}->{EmailAddress} || "";
        next unless $address;
        printf("%s - %s <%s>\n", $oldmembers{$id}->{Name}, $id, $address);
    }
    exit 0;
}

if (@removed) {
    print scalar(@removed)," removed from the register\n\n";
    list_members(\%oldmembers, sort oldnamesort @removed);
    print "\n";
}
if (@gain) {
    print scalar(@gain)," new members\n\n";
    list_members(\%newmembers, sort newnamesort @gain);
    print "\n";
}
if (@loss) {
    print scalar(@loss)," no longer members\n\n";
    list_members(\%oldmembers, sort oldnamesort @loss);
    print "\n";
}
if (@changed) {
    print scalar(@changed)," changed membership status\n\n";
    list_members(\%newmembers, sort newnamesort @changed);
    print "\n";
}

if (@emailchanged) {
    print scalar(@emailchanged)," changed email address\n\n";
    for my $id (sort newnamesort @emailchanged) {
	printf("  %-24s %s->%s\n",
	       $newmembers{$id}->{Name},
	       $oldmembers{$id}->{EmailAddress} || "''",
	       $newmembers{$id}->{EmailAddress} || "''",
	       );
    }
    print "\n";
}

if (@addrchanged) {
    print scalar(@addrchanged)," changed postal address\n\n";
    for my $id (sort newnamesort @addrchanged) {
	printf("  %-24s (fra->til)\n", $newmembers{$id}->{Name});
	for my $key (qw(Address1 Address2 Address3 PostCode)) {
	    my $old = $oldmembers{$id}->{$key} || '';
	    my $new = $newmembers{$id}->{$key} || '';
	    if ($key eq "PostCode") {
		$old .= " " . $oldmembers{$id}->{PostOffice} || '';
		$new .= " " . $newmembers{$id}->{PostOffice} || '';
		$old =~ s/^ *$//g;
		$new =~ s/^ *$//g;
	    }
	    unless ('' eq $new && '' eq $old) {
		printf(" %10s %-30s", "", "'$old'");
		printf(" -> %-30s", "'$new'") unless ($old eq $new);
		print "\n";
	    }
	}
    }
    print "\n";
}

sub oldnamesort {
    return $oldmembers{$a}->{Name} cmp $oldmembers{$b}->{Name};
}

sub newnamesort {
    return $newmembers{$a}->{Name} cmp $newmembers{$b}->{Name};
}

sub addr_string {
    my $memberinforef = shift;
    my $str;
    for my $key (qw(Address1 Address2 Address3 PostCode PostOffice)) {
        my $value = $memberinforef->{$key};
        $value =~ s/ *(\S.+\S+) */$1/;
        $str .= $value . ", ";
    }
    return $str;
}

sub list_members {
    my ($hashref, @idlist) = @_;
    for my $id (@idlist) {
	printf("  %-24s %-27s %-20s\n",
	       $hashref->{$id}->{Name},
	       $hashref->{$id}->{ZUsrArbeidsgiver},
	       $hashref->{$id}->{ZUsrMedlemstatus},
	       );
    }
}

sub process_entry {
    my ($memberinforef, $hashref) = @_;
    $hashref->{$memberinforef->{'CustomerNo'}} = $memberinforef;
    $memberids{$memberinforef->{'CustomerNo'}}++;
}

sub show_changes {
    my $id = shift;
    for my $key (qw(Name ZUsrMedlemstatus)) {
	printf("  %-17s %-27s -> %-27s\n", $key,
	       $oldmembers{$id}->{$key} || "",
	       $newmembers{$id}->{$key} || "");
    }
}
