use utf8;
use warnings; no warnings "redefine";
use strict;
use Loader qw(line_in);

=head1 select_date

C<select_date( Flags [Prompt] [Default] [ID => Hilfstext] )>

Fragt vom Anwender ein Datum ab.

Folgende Flags sind definiert:

=over 4

=item 1

Es sind keine Zeitangaben möglich.

=item 2

Es sind keine Datumsangaben möglich; die Zeit ist ein Intervall.

=item 4

Es sind nur Monatsangaben möglich.

=item 8

Ohne Datumsangabe wird der Tag des Defaults oder der heutige Tag verwendet.

=item 16

Ohne Tagesangabe wird das Ende des angegebenen Monats zurückgeliefert.

=item 32

Ohne Zeitangabe wird das Ende des angegebenen Tages zurückgeliefert.

=item 64

Das Intervall darf länger als 24 Stunden sein.

=item 128

Negative Angaben sind OK.

=item 256

'=' als Eingabe ("jetzt") ist OK.

=item 512

'x' als Eingabe ("immer") ist OK.

=item 1024

'0' als Eingabe ("unbegrenzt") ist OK.

=item 2048

Filtere den Default und liefere ihn direkt zurück

=item 4096

Filtere den Default bei Leereingabe.

=back

=cut

use Dbase::Help qw(unixdate isodate isotime DoTime);

sub select_date($;$$@) {
	my($flags,$kn,$defdatum,@addhelp) = @_;
	my %addhelp = @addhelp;

	if(defined $kn and $kn =~ s/^\s+//) {
		$kn = "### $kn";
	} elsif(not defined $kn or $kn eq "") {
		$kn = "Datum";
	}
	my $act = "";
	$act = "run" if $flags & 2048;
	while(1) {
		if($act eq "run") {
			my($j,$m,$t,$hh,$mm,$ss) = isotime($defdatum||DoTime);
			if($flags & (4|16)) {
				$act = sprintf "%04d-%02d",$j,$m;
			} elsif($flags & (1|32)) {
				$act = sprintf "%04d-%02d-%02d",$j,$m,$t;
			} elsif($flags & 2) {
				$act = sprintf "%02d:%02d:%02d",$hh,$mm,$ss;
			} else {
				$act = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $j,$m,$t, $hh,$mm,$ss;
			}
		} else {
			$act = line_in "$kn> "; return undef if $act eq "";
			if($act eq "" and $flags & 4096) {
				$flags &=~ 4096;
				$act = "run";
				next;
			}
		}
		return "=" if $act eq "=" and $flags & 256;
		return "x" if $act eq "x" and $flags & 512;
		return "0" if $act eq "0" and $flags & 1024;
		return $act if $act =~ s/^\+(\d+)\+$/$1/;
		my $neg = 1;

		if($act eq '?') {
			my $dd = isodate($defdatum || DoTime);

			print <<END unless $flags & (1|2|4);
YYYY-MM-DD HH:MM Datum mit Tageszeit
END
			print <<END unless $flags & (2|4);
YYYY-MM-DD       Datum
END
			print <<END unless $flags & 2;
YYYY-MM          Monat, bzw. Monatsanfang
END
			if ($flags & 8) {
				print <<END if $flags & 2;
HH:MM            Uhrzeit (am $dd) 
END
			} else {
				print <<END unless $flags & 1;
HH:MM            Stunden+Minuten
HH               Stunden
END
			}

			my @ah = @addhelp;
			while(@ah) {
				my $k = shift @ah;
				my $v = shift @ah;
				printf "%-16s %s\n",$k,$v;
			}
			next;
		}
		return $act if $addhelp{$act};

		my $date;
		my $did = 0;

		if($flags & 128 and $act =~ s/^-(.+)/$1/) {
			$neg = -$neg;
		}
		if($act =~ s/^(\d\d\d\d)-?(\d\d)(?:-(\d\d))?//) {
			if($flags & 2) {
				print "...hier kann nur eine Zeit angegeben werden.\n";
				next;
			}
			if($3) {
				if($flags & 4) {
					print "...hier kann nur ein Monat angegeben werden.\n";
					next;
				}
				$date = unixdate($1,$2,$3);
			} else {
				if($flags & 16) {
					my $yy = $1; my $mm = $2;
					if(++$mm > 12) { $mm = 1; $yy++; }
					$date = unixdate($yy,$mm,1);
					$did = 2;
				} else {
					$date = unixdate($1,$2,1);
				}
			}
			$act =~ s/^\s+//;
			$did = 1 unless $did;
		} elsif($flags & (2|8)) {
			if($flags & 8) {
				$date = $defdatum || DoTime;
				my($j,$m,$t)=isodate($date);
				$date = unixdate($j,$m,$t);
			} else {
				$date = 0;
			}
		} else {
			print "'$act' verstehe ich nicht.\n";
			next;
		}
		if(($flags & 64) ? ($act =~ s/^(\d+):(\d\d?)(?::(\d\d?))?\s*//) : ($act =~ s/^(\d\d?):(\d\d?)(?::(\d\d?))?\s*//)) {
			if ($flags & 1) {
				print "...hier kann nur ein Datum angegeben werden.\n";
				next;
			}
			if($1*3600+$2*60+($3||0) > 24*60*60 and not $flags & 64) {
				print "Zeitraum <= 24 Stunden!\n";
				next;
			}
			if($2 >= 60 or $3 and $3 >= 60) {
				print "'$act' verstehe ich nicht.\n";
				next;
			}
			$date += $1*3600+$2*60;
			$date += $3 if $3;
			return $neg*$date if $act eq "";
		} elsif($flags & 2 and $act =~ /^\d+$/) {
			return $neg*$act*3600 if $act <= 24 or $flags & 64;
		} elsif($did) {
			if($act eq "") {
				$date += 25*60*60 if $flags & 32 and $did != 2;
				## Sommerzeitumstellungsgeraffel beachten...
				my($j,$m,$t)=isodate($date);
				return unixdate($j,$m,$t);
			}
		}
		print "'$act' verstehe ich nicht.\n";
		next;
	}
}
1;
