use utf8;
use strict;
use warnings; no warnings qw(redefine);
use Dbase::Help qw(DoFn);
use Dbase::Globals qw(bignum get_gruppen get_descr);
use Dbase::IP;
use Fehler qw(problem);
use Loader qw(walk_ip line_printer);

my @lastnet;

sub initlast($) {
    my($net) = @_;
	$lastnet[$net->db_bits] = $net;
	foreach my $i(0..$net->db_bits-1) {
		$lastnet[$i] = undef;
	}
	$net;
}

sub setlast($$) {
    my($net,$maxbits) = @_;

	my $i = $net->db_bits+1;
	while($i < $maxbits) {
		next unless defined $lastnet[$i];
		return undef if $lastnet[$i]+1 > $net;
		return initlast($net->bitmask($i,1));
	} continue {
		$i++;
	}
	undef;
}

my $res;
sub do_check($$;$) {
	my($ip,$lim,$flag) = @_;
	return unless $flag&2;
	return if not $ip->is_v4;

	$ip = $ip ->bitmask(0);
	$lim= $lim->bitmask(0);

	return if $lim-$ip >= 256;

	require noris::DNS::Resolver;
	$res ||= noris::DNS::Resolver->new;

	while($ip < $lim) {
		my $q = $res->query($ip->revstr,"PTR");
		if ( $q and ( my @fqdns = map $_->ptrdname, grep $_->type eq 'PTR', $q->answer ) ) {
			printf $Db::pr_fh "%-31s /%2d %s\n",
			                  ' 'x(16).$ip->str(4), $ip->is_v4 ? 32 : 128, join '/', sort @fqdns;
		}
	} continue {
		$ip++;
	}
}

## Flags&1: Einzeladressen
## Flags&2: DNS
## Flags&4: Ziele
## Flags&8: VRFs-Präfix nicht mit ausgeben

sub map_ip($;$$@) {
    my($net,$flags,$ipflags_wanted,@kunden) = @_;

	my($ipflags_grs,$ipflags_grc);
	($ipflags_grs,$ipflags_grc) = get_gruppen( ipflags => $ipflags_wanted, 1 )
	  or return
	  if defined $ipflags_wanted;

	line_printer;

	my $lim = $net+1;

	initlast($net);
	my $lip = $net;
	my %kd;
	foreach my $k(@kunden) {
		$kd{$k}++;
	}

	walk_ip($net, sub {
		my($id,$ip,$f1,$z)=@_;

		my $iip = setlast($ip,$net->db_bits);
		do_check($lip,$ip,$flags); $lip = $ip;
		if($flags&1 or $ip->db_bits) {
			my ( $kunde_id, $kunde_name, $inf, $ipflags ) = DoFn(<<_);
	SELECT kunde.id, kunde.name, ipkunde.name, ipkunde.flags
	FROM   ipkunde, kunde
	WHERE  ipkunde.id = $id
	   AND kunde.id = ipkunde.kunde
_
			$ipflags = bignum($ipflags);
			if ( !@kunden || $kd{$kunde_id} and !defined $ipflags_wanted || ($ipflags & $ipflags_grs) == $ipflags_grs && not $ipflags & $ipflags_grc ) {
				my $indent;

				if($iip) {
					$indent = $iip->masklen-$net->masklen;
					do_check($lip,$iip,$flags); $lip = $iip;
					print $Db::pr_fh " "x$indent," ",$iip->str(4|($flags&8)),"\n";
				}

				$inf = defined $inf && ": $inf";
				$indent = $ip->masklen-$net->masklen;
				$indent=32 if $indent>32;
				if($flags&4 and defined $z) {
					printf $Db::pr_fh "%s %s [%s] %s%s\n"," "x$indent,$ip->str(($flags&8)?4|8:0),get_descr("ziel",$z),$kunde_name,$inf;
				} else {
					printf $Db::pr_fh "%s %s %s%s\n"," "x$indent,$ip->str(($flags&8)?4|8:0),$kunde_name,$inf;
				}
			}
		}

		initlast($ip);
	},2|8|16);
	do_check($lip,$lim,$flags);
}

1;
