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

use Dbase::Globals qw(get_ipkunde get_kunde name_kunde get_vrf get_gruppen unterkunden);
use Dbase::Help qw(DoFn DoSelect qquote);
use Loader qw(add_kunde_ipaddr edit_ipaddr line_in list_ipaddrs log_view
	valid_ip add_ipaddr_vrf list_vrfs select_suche);
use Fehler qw(problem report_fehler report_status warnung);
use Dbase::IP;

my %suche = (
	f  => sub {
		my ($grs, $grc) = get_gruppen( ipflags => $_[0], 1 ) or return;
		"(flags & $grs = $grs AND flags & $grc = 0)";
	},
	hg => sub {
		my($str,$key) = @_;
		$_ = $str;
		if ( $key eq '-' ) {
			return problem("Suche mit '-' nur ohne Text") if length $_;
			return <<'_';
  ipkunde.id IN (
    SELECT ip_hostgroup.host
      FROM ip_hostgroup,hostgroup
     WHERE ip_hostgroup.gruppe=hostgroup.id
       AND hostgroup.name IS NULL )
_
		}
		elsif ( $key eq '?' ) {
			$_ = "%$_" unless /^%/;
			$_ .= '%' unless /%$/;
		}
		"ipkunde.id in (select ip_hostgroup.host from ip_hostgroup,hostgroup
			where ip_hostgroup.gruppe=hostgroup.id
			  and hostgroup.name like ${\ qquote($_) } )"
	},
	n  => 'name',
	i  => 'infotext',
);

# Flags: 1: Return mit Eintrag
#        2: nur Selektion von Hostadressen erlaubt
#        4: '-' erlaubt
sub edit_ipaddrs($;$$) {
	my($id,$flag,$kn) = @_;

	$kn = "Kunde $id:" .name_kunde($id) if $kn eq "";

	aloop: while(1) {
		my $act = line_in "$kn IP >", $flag&1 ? 0 : 4;
		return undef unless defined $act && length $act;
		( $act, my @select ) = split ' ', $act;

		for (@select) {
			if ( $_ eq '/' ) {
				$_ = 'bits > 0';
			}
			elsif (/^#(.*)/) {
				my $ip = get_ipkunde( $1, 2 );
				if ($ip) {
					my $bits;
					( $ip, $bits ) =
					  DoFn("select ip6,bits from ipkunde where id=$ip")
					  and $ip = Dbase::IP->new_db( $ip, $bits );
				}
				else {
					$ip = Dbase::IP->new($1);
				}

				if ($ip) {
					$_ = 'ip6 >= '
					  . qquote( $ip->db_ip6 )
					  . ' AND ip6 < '
					  . qquote( ( $ip + 1 )->db_ip6 )
					  . ' AND bits <= '
					  . $ip->db_bits;
				}
				else {
					problem("IP-Adressobjekt $_ nicht gefunden.");
					next aloop;
				}
			}
			else {
				defined( $_ = select_suche( $_, ipkunde => %suche ) )
				  or next aloop;
			}
		}

		if($act eq "?") {
			print <<'END';

l       aktive IPv4-Objekte (mit VRFs) anzeigen       L   auch beendete ...
l4      aktive IPv4-Objekte (ohne VRFs) anzeigen      L4
l6      aktive IPv6-Objekte anzeigen                  L6
ll      alle aktiven Objekte anzeigen                 LL
*l, *L, etc.: auch mit Unterkunden

Ein bestimmtes VRF kann mit vorangestelltem "vrf!..." ausgewählt werden.
(Name oder Nummer)
Zusätzlich können beliebig viele mit Whitespace getrennte Suchargumente
übergeben werden:

#NETZ  zeigt nur Adressen innerhalb dieses Netz(objekt)s
/      zeigt nur Netzbereiche

Folgende Suchoptionen sind möglich:
n  nach Name
i  nach Infotext
hg nur Adressen in Hostgroups anzeigen, deren Name als (siehe Optionen) passt

Wenn man diese mit folgenden benutzt:
:... wird ... als SQL-Wildcard "..." zur Suche im Feld verwendet
?... werden Einträge angezeigt in desen Feld "..." vorkommt
-    werden Einträge angezeigt deren Feld leer (NULL) ist

Zusätzliche Suchmöglichkeiten
f:...  nur Adressen mit diesen Flags anzeigen

Beispiele:
* "ll n?Blub"  zeige alle aktiven Adressen an, in deren Name "Blub" vorkommt.
* "ll i-"      zeige alle aktiven Adressen an, die keinen Infotext haben
* "ll f:monitoring,!no_mx"  zeige alle aktiven Adressen an, bei denen das
  monitoring- aber nicht das no_mx-Flag an ist

a      hinzufügen           v   neues VRF anlegen    lv  VRFs auflisten

END
			print <<'END' if $flag & 4;
-        disassoziieren
END
			if($flag & 1) {
				print <<'END';
####     Subnetz auswählen
!####    Subnetz editieren
END
			} else {
				print <<'END';
####     Subnetz editieren
END
			}
			print <<'END';
IPNR     dito (auch Netze)
NAME     dito (Rechner- bzw. Subnetz-Name)
END
			next;
		}

		if($act eq "a") {
			my $kunde_id = $id;
			until ($kunde_id) {
				length( my $kunde = line_in 'Kunde      > ' ) or return;
				$kunde_id = get_kunde $kunde and last;
				print
				  qq(Kunde "$kunde" ist mit nicht bekannt; bitte versuch's nochmal:\n);
			}
			my $ret = add_kunde_ipaddr($id,$kn);
			return $ret if $flag & 1 and $ret > 0;
			next;
		}
		if($act eq "v") {
			my $ret = add_ipaddr_vrf($id,$kn);
			return $ret if $flag & 1 and $ret > 0;
			next;
		}
		if($act eq "lv") {
			list_vrfs($id);
			next;
		}
		if ( $act =~ / ^ (\*)? (?:( \w* )\!)? ( [lL] ) ( [46lL] )? \z /x ) {
			my $vrf;
			if(defined $2 and $2 ne "") {
				$vrf = get_vrf($2);
				problem "Das VRF '$2' kenne ich nicht", next
					unless defined $vrf;
			}
			my $flags;
			$flags |= 8 if defined $2 and $2 eq "";
			$flags |= 1 if $3 eq 'L';
			$flags |= ($4 eq '6') ? 12 : ($4 eq '4') ? 8 : 4
				if defined $4;
			list_ipaddrs( ($1 && $id) ? [ unterkunden($id) ] : $id, $kn, $flags, $vrf, @select);
			next aloop;
		}
		if($act eq "H") { log_view($kn,"ipkunde"); next; }
		return $act if $act eq "-" and $flag & 4;
		my $force = ($act =~ s/^\?//);
		my $eip = Dbase::IP->new($act);

		if($act =~ s/^I?(\d+)$/$1/) {
			my($ip,$bits) = DoFn("select ip6,bits from ipkunde where id=$act");
			$eip = Dbase::IP->new_db($ip,$bits);

			if($flag & 1 and not $force) {
				return unless valid_ip($act);
				return $act;
			}
			edit_ipaddr($act,$id,$kn);
			next;
		} elsif(defined $eip) { # gültige Adresse eingegeben

			my $ipa = get_ipkunde( $eip, $flag&2 );
			if(not defined $ipa) {
				print "IP-Adresse '$act' nicht gefunden.\n";
				next;
			}

			my($ip,$bits) = DoFn("SELECT ip6,bits FROM ipkunde WHERE id = $ipa");

			if($flag & 2) {
				if($bits) {
					print STDERR "Nur Hostadressen sind hier erlaubt!\n";
					next aloop;
				}
			}
			$ip = Dbase::IP->new_db($ip,$bits);

			if ($ip->db_bits != $eip->db_bits) {
				my $ip = $ip->str(4);
				if ( $flag & 1 ) {
					problem("Ein solches Objekt gibt es nicht. (Nächstgrößerer Adressbereich: $ip)");
					next aloop;
				}
				else {
					warnung("Es wurde nur der übergeordnete IP-Adressbereich '$ip' gefunden.");
				}
				#report_status();
				#my $answer = line_in( 'Aufrufen? ' );
				#next aloop if $answer !~ /^[jy]/i;
			}

			if($flag & 1 and not $force) {
				return unless valid_ip($ipa);
				return $ipa;
			}
			edit_ipaddr($ipa,$id,$kn);
			next;
		} else {
			my $ipa;
			my $aktiv = '( ende IS NULL OR ende >= UNIX_TIMESTAMP(NOW()) )';

                        # Erstmal schauen, ob's ein _aktives_ Objekt mit passendem FQDN gibt,
                        # nur falls nicht, interessieren uns ggf. beendete Objekte:
			my @suchen = (
				[ " AND $aktiv", 'mehrere aktive' ],
				[ '',            'mehrere beendete' ]
			);

                        # Falls wir uns in einem bestimmten Kunden (und nicht unter "alle Kunden")
                        # befinden, suche erst speziell nach passenden Objekten bei diesem Kunden
                        # und nur, wenn es da keines gibt, auch bei anderen:
			@suchen =
			  map +(
				[ " AND kunde = $id$_->[0]", "bei diesem Kunden $_->[1]" ], $_
			  ),
			  @suchen
			  if defined $id;

                        for (@suchen) {
				my($sql, $descr) = @$_;
				DoSelect {
					if ($ipa) {
						warnung "Es gibt $descr IP-Adress-Objekte dieses Namens (#$ipa vs. #$_[0]).";
					}
					else {
						$ipa = shift;
						warnung('Dieses IP-Adressobjekt ist bereits beendet.') if shift;
					}
				} "SELECT id, ende IS NOT NULL AND ende <= UNIX_TIMESTAMP(NOW()) FROM ipkunde WHERE name = ${\qquote $act} $sql ORDER BY id";
				last if defined $ipa;
			}
			if(defined $ipa) {
				return $ipa if $flag & 1 and !$force;
				edit_ipaddr($ipa,$id,$kn);
				next;
			}
		} ## FALL THRU

		print "Aktion '$act' kenne ich nicht. Liste mit '?'.\n";
		next; fehler: report_fehler(4);
	}
	undef;
}

1;
