use utf8;
use warnings; no warnings "redefine";
use strict;

use Dbase::Globals qw(
  aufzaehlung
  beendet
  flag_names
  get_descr
  hostgroupinfo
  name_kunde
  persinfo
  mpersinfo
  name_dienst
);
use Dbase::Help qw(DoSelect isotime DoFn);
use Dbase::Globals qw(find_descr);
use Fehler qw(problem warnung);
use Loader qw(line_printer ticket_get_header);
use Socket qw(AF_INET AF_INET6);
use Socket6 qw(gethostbyname2 inet_ntop);
use Dbase::IP;
use Cf qw($VRF_PREFIX);

my $show_tree;
$show_tree = sub {
	my ($prefix,$mode,$id) = @_;
	DoSelect {
		my ( $other, $ip,$bits, $fqdn ) = @_;
		$ip = Dbase::IP->new_db($ip,$bits);
		printf $Db::pr_fh "%-10s: #%d:%s%s\n",
		                  $prefix, $other, $ip->str(4), defined $fqdn && " ($fqdn)";
		$show_tree->(">$prefix", $mode, $other);
	} <<_
	SELECT    ipkunde.id, ipkunde.ip6,ipkunde.bits, ipkunde.name
	FROM      ipkunde, iptree
	WHERE     iptree.${ { child=>\'parent', parent=>\'child' }->{$mode} } = $id
	      AND iptree.$mode = ipkunde.id
	      AND ( ipkunde.ende IS NULL OR
	            ipkunde.ende >= UNIX_TIMESTAMP(NOW())    )
_
};

my $print_hardware = sub ($$$) {
	my ( $prefix, $id, $name, $ende ) = @_;
	printf $Db::pr_fh "%-10s: #%i: %s%s\n", $prefix, $id, $name, beendet($ende);
};

my $vnr;
sub list_ipnr($;$) {
	my($idi,$kn) = @_;
	line_printer;

	DoSelect {
		my (
			$timestamp,      $ip,     $ipbits,  $kunde,
			$kiste,          $tarif,  $beginn,  $ende,
			$name,           $info,   $alloc,   $mac,
			$region,         $ticket, $ziel,    $nagiosconf,
			$snmp_community, $flags,  $owner,   $adminc,
			$techc,          $nic,    $mail_ip, $vrf,
		) = @_;

		$ip = Dbase::IP->new_db($ip,$ipbits);

		print $Db::pr_fh "ID        : $idi\n";
		print $Db::pr_fh "Timestamp : ".isotime($timestamp)."\n";
		$vnr = Dbase::IP->new($VRF_PREFIX)
			unless defined $vnr;
		if(defined $vrf) {
			my $vnr = $ip - (Dbase::IP->new($VRF_PREFIX)->bitmask(32));
			print $Db::pr_fh "VRF       : $vnr $vrf\n" if defined $vrf;
			print $Db::pr_fh "Adresse   : $ip\n";
		} elsif($ip->is_v4rf == 2) {
			my $vip = $ip->bitmask(32,1);
			my $mip = $ip->mask4;
			my($vname,$kd) = DoFn "select vrf,kunde from ipkunde where ${\$vip->dbs}";
			$vname = "? ".($vip - $vnr->bitmask(32)) if not defined $vname;
			my $kinfo = !defined $kd
			  || $kd == $kunde
			  ? ''
			  : " (VRF von #$kunde:${\name_kunde $kunde}!)";

			print $Db::pr_fh "Adresse   : $vname!$mip$kinfo\n";
		} else {
			print $Db::pr_fh "Adresse   : $ip\n";
		}
		print $Db::pr_fh "Kunde     : #$kunde:".name_kunde($kunde)."\n" if $kunde;
		print $Db::pr_fh "Gateway   : $kiste\n" if defined $kiste;
 		if(defined $mac) {
			$mac =~ s/(..)/$1:/g; chop $mac;
			print $Db::pr_fh "MAC-Adr.  : $mac\n"; }
		print $Db::pr_fh "Dienst    : ".name_dienst($tarif)."\n";
		print $Db::pr_fh "Ziel      : ".(get_descr("ziel",$ziel)||'???')."\n" if defined $ziel;
		print $Db::pr_fh "Beginn    : ".isotime($beginn)."\n" if $beginn;
		print $Db::pr_fh "Ende      : ".isotime($ende)."\n" if $ende;
		print $Db::pr_fh "Registrar : ".get_descr('nic',$nic)."\n" if $nic;
		print $Db::pr_fh "Firma     : #$owner:".mpersinfo($owner)."\n" if $owner;
		print $Db::pr_fh "Admin-C   : #$adminc:".mpersinfo($adminc)."\n"
if $adminc;
		print $Db::pr_fh "Tech-C    : #$techc:".mpersinfo($techc)."\n" if $techc;
		print $Db::pr_fh "NagiosConf: $nagiosconf\n" if defined $nagiosconf;

		DoSelect { printf $Db::pr_fh 'in H.group: ' . hostgroupinfo(@_) . "\n" }
		<<_;
	SELECT   hostgroup.id, hostgroup.name, hostgroup.beschreibung
	FROM     hostgroup, ip_hostgroup
	WHERE    ip_hostgroup.gruppe = hostgroup.id
	     AND ip_hostgroup.host   = $idi
	ORDER BY hostgroup.name
_
		print $Db::pr_fh "SNMP-Comm.: $snmp_community\n" if defined $snmp_community;
		print $Db::pr_fh "Mail-IP   : *.$mail_ip\n" if defined $mail_ip;
		print $Db::pr_fh 'Flags     : '.flag_names($flags,'ipflags')."\n";

		my ( $hwkunde, $hwstandort ) =
		  DoFn "SELECT kunde, standort FROM hardware WHERE ip = $idi";

		if ($hwstandort) {

			my $mondienst = find_descr( 'dienst' => 'mon-standort' );
			if ( defined $hwkunde and $hwkunde != 1 and defined $hwstandort and defined $mondienst ) {
				my $kunde = DoFn  <<_;
    SELECT kunde.name
      FROM kunde, kundemail
     WHERE kunde.id = kundemail.kunde
       AND kundemail.person = $hwstandort
       AND ( kunde.ende IS NULL OR kunde.ende >= UNIX_TIMESTAMP(NOW()) )
       AND kundemail.dienst = $mondienst
       AND kundemail.kunde = $hwkunde
  ORDER BY kunde.name
_
				printf $Db::pr_fh "Monitoring: bei Monitoringstandort\n" if $kunde;
			}
		}

		# Trennung von Variablen-Deklaration und bedingter
		# Initialisierung wichtig, vgl. RT#244828:
		print $Db::pr_fh ($ipbits ? 'Netzname  : ' : 'FQDN      : ') . "$name\n" if defined $name;
		print $Db::pr_fh "Zusatzinfo: $info\n" if defined $info;
		print $Db::pr_fh "Alloc     : ".DoFn("select zone from ipregion where id = $region")."\n" if $region;
		print $Db::pr_fh "Ticket K  : ".ticket_get_header($ticket,32768|1) if $ticket;
		$show_tree->( Parent => parent => $idi );
		$show_tree->( Child  => child  => $idi );

		DoSelect { $print_hardware->( Hardware => @_ ) }
		  "SELECT id, name, ende FROM hardware WHERE ip = $idi";

		DoSelect { $print_hardware->( 'HW-Interf.' => @_ ) } <<_;
	SELECT   hardware.id, hardware.name, hardware.ende
	FROM     hardware
	JOIN     hardware_ip ON hardware_ip.hardware = hardware.id
	WHERE    hardware_ip.ip = $idi
	ORDER BY hardware.name, hardware.ip
_
		for (
			[ 'PeerIP für' => "SELECT id     FROM person WHERE uremip = $idi ORDER BY id"     ],
			[ 'Route bei'  => "SELECT person FROM ipmap WHERE ipkunde = $idi ORDER BY person" ],
		) {
			my $prefix = $_->[0];
			DoSelect {
				my($person) = @_;
				printf $Db::pr_fh "%-10s: %s\n", $prefix, persinfo($person);
				$prefix = '';
			} $_->[1];
		}

		unless ($ipbits) {
			if ( defined $name ) {
				unless (
					my (
						$h_name,   $h_aliases, $h_addrtype,
						$h_length, @h_addr_list
					)
					= $ip->is_v4
					? gethostbyname $name
					: gethostbyname2( $name, AF_INET6 )
				  )
				{
					warnung('Für diesen FQDN gibt es im DNS offenbar keine IPv'
						  . ( $ip->is_v4 ? 4 : 6 )
						  . '-Adresse.' );
				}
				else {
					$_ = Dbase::IP->new(inet_ntop(
							((length($_) == 4) ? AF_INET : AF_INET6), $_)
						)->str(4) for @h_addr_list;

					warnung('Für diesen FQDN '
						  . ( @h_addr_list == 1 ? 'ist' : 'sind' )
						  . ' im DNS folgende IPv'
						  . ( $ip->is_v4 ? 4 : 6 )
						  . '-Adresse'
						  . ( @h_addr_list != 1 && 'n' )
						  . " eingetragen:\n"
						  . aufzaehlung(@h_addr_list) )
					  unless grep $_ eq $ip->str(4), @h_addr_list;
				}
			}
			if ( defined( my $dnsname = gethostbyaddr ($ip->aton, $ip->is_v4 ? AF_INET : AF_INET6 ) ) ) {
				warnung "Für diese IP-Adresse besteht im DNS ein auf $dnsname zeigender Reverse-Eintrag."
					unless defined $name && $name eq $dnsname;
			}
			elsif ( defined $name ) {
				warnung('Für diese IP-Adresse existiert im DNS offenbar kein Reverse-Eintrag.');
			}
		}
		
	} <<_ or problem("IP-Adresse '$idi' unbekannt");
	SELECT timestamp,
	       ip6,bits,
	       kunde,
	       kiste,
	       tarif,
	       beginn,
	       ende,
	       name,
	       infotext,
	       alloc,
	       mac,
	       ipregion,
	       ticket,
	       dest,
	       nagiosconf,
	       snmp_community,
	       flags,
	       owner,
	       adminc,
	       techc,
	       nic,
	       mail_ip,
		   vrf
	FROM   ipkunde
	WHERE  id = $idi
_
}

1;
