#!/usr/bin/perl
use warnings;
use strict;
use IO::File;

my $err = 0;
die "$0: old-zone-info new-zone-info\n" unless @ARGV == 2;

my ($oldzone, $newzone) = @ARGV;

my @difflines = `/usr/bin/diff -u $oldzone $newzone`;

exit 0 if @difflines == 0;  # no differences

chomp @difflines;
shift @difflines; shift @difflines; # --- and +++

my $fh = new IO::File $newzone, "r" or die "Failed to open '${newzone}': $!\n";
my @zlines = grep {m/^Z/} $fh->getlines;
$fh->close;
chomp @zlines;
map {s/^Z([^:]+):.*$/lc $1/e} @zlines;
@zlines = sort { length $b <=> length $a } @zlines;
# Now inherently the first match against an entry is going to match the
# deepest subdom for which there's a distinct SOA

my @changed_zones;
#my @updated_soas;
my (%soa_old, %soa_new);

# Zdomain.tld:primary.ns.server:hostmaster.domain.tld:serial  [:....]
foreach (@difflines) {
	next unless /^[-+]/;
	next if /^[+-]#/;
# print ".$_\n";
	if (m/^([+-])(.)([^:]*):/) {
		my ($ft, $type, $host) = ($1, $2, lc $3);
		my $dom = $host;
		if ($type ne 'Z') {
			foreach (@zlines) {
				if ($host =~ /\Q$_\E$/) {
					$dom = $_;
					last;
				}
			}
		}
		push @changed_zones, $dom;
		if ($type eq 'Z') {
			if (not /^.Z[^:]+:[^:]+:[^:]+:([^:]+)/) {
				warn "Bad zone entry for '${host}'\n";
				++$err;
			}
			my $serial = $1;
			if ($ft eq '-') {
				warn "Were dup Z entries for '${host}'\n"
					if exists $soa_old{$host};
				$soa_old{$host} = $serial;
			} else {
				if (exists $soa_new{$host}) {
					warn "Error: dup Z entries for '${host}'\n";
					++$err;
				}
				$soa_new{$host} = $serial;
			}
		}
	} else {
		warn "Unable to parse diff line:\n{ $_ }\n";
	}
}
my @zonelist;
my $last = undef;
foreach (sort @changed_zones) {
	next if defined $last and $last eq $_;
	$last = $_;
	push @zonelist, $_;
}
$last = undef;
# print "$_\n" foreach @zlines;
if (@zonelist) {
	print "Changed zones:\n";
	foreach (@zonelist) {
		print "  $_\t";
		if (exists $soa_new{$_}) {
			print "okay " . (
				exists $soa_old{$_} ?
					"$soa_old{$_} -> " :
					'new '
				) . $soa_new{$_};
		} else {
			++$err;
			print "ERR - no updated SOA serial";
		}
		print "\n";
	}
}
exit $err;
