use utf8;
use warnings; no warnings "redefine";
use strict;
use Loader qw(
	crypter
	editor
	line_in
	line_print_end
	line_printer
	log_update
	set_kunde_passwort
	valid_kunde
	warn_arbeit
  );
use Dbase::Help qw(Do DoFn DoSelect DoTrans DoBinary in_list isotime qquote);
use Dbase::Globals qw(
  aufzaehlung
  content
  find_descr
  get_descr
  name_kunde
  unterkunden
);
use Fehler qw(problem fehler);

my @last_read;
my @pw;
my @neu;

use IO::Pipe;
use Fehler qw(ffehler);

## Flags: 1 angucken, 2: PW ändern, 4: alte Daten ignorieren

sub edit_kunde_passwort($;$$$) {
	my($id,$flag,$kn,$opp) = @_;

	return unless valid_kunde($id);
	
	# Nur warnen, wenn editiert wird
	my $work;
	unless($flag & 1) {
		# eigentlich sollten die eigenen Datensätze hier ignoriert werden,
		# jedoch wird der Datensatz wegen der abgebrochenen Transaktion
		# nicht automagisch gelöscht.
		$work = warn_arbeit("passwort",$id,"*",$kn, 4, 8*60);
		return unless defined $work;
	}

	my $pw = DoFn("select pwklasse from kunde where id = $id");
	set_kunde_passwort( $id, $pw = find_descr( passwort => 'standard' ) )
	  unless defined $pw;
	my $pwklasse = get_descr( passwort => $pw );

	$pw = 99+$id if $pw == 0;

	unless(defined $pw[$pw] and $last_read[$pw] > time-5*60 and not $opp) {
		$pw[$pw] = line_in( "Passwort $pwklasse: ", 1 );
		return undef unless defined $pw[$pw];
		$neu[$pw]=1;
	}
	$last_read[$pw]=time;

	if($flag&2 and not $flag&4) {
		# Passwort dieser Klasse global ändern
		my @knd;
		my $opw = $pw[$pw];
		my $npw = line_in("Neues Passwort: ",1);
		return undef unless $npw ne "";
		my $ver = line_in("Nochmal: ",1);
		return undef unless $ver ne "";
		return problem "So nicht... bitte Fingerübungen machen und nochmal probieren.\n"
			if $ver ne $npw;
		
		$pw[$pw] = $npw;

		if($pw>=100) {
			@knd = ($id);
			log_update("passwort","id",$id,undef,"passwort");
		} else {
			log_update("passwort","pwklasse",$pw,undef,"passwort");
			@knd = ();
			DoSelect { push(@knd,$_[0]) } "select id from kunde where pwklasse = $pw";
		}
		print STDERR "Start...\n";
		foreach my $k(@knd) {
			local $|=1;
			print STDERR "\r  ".name_kunde($k)."           \r1";
			DoBinary {
				my($pp,$pseq) = DoFn("select pass,seq from passwort where kunde = $k order by seq desc limit 1");
				unless ( content($pp) ) {
					print STDERR name_kunde($k).": kein Passwort gespeichert\n";
					return;
				}
			
				print STDERR "\r2";
				ffehler {
					$pp = crypter $pp,$opw,1;
				} sub {
					undef $pp;
					goto fehler;
				};

				print STDERR "\r3";
				ffehler {
					$pp = crypter $pp,$pw[$pw],2;
				} sub {
					undef $pp;
					goto fehler;
				};

				print STDERR "\r4";
				$pseq = 1+$pseq;
				DoBinary {
					Do("insert into passwort set kunde=$k, seq=$pseq, pass=${\qquote $pp}");
				};
				return;
			fehler:
				return problem name_kunde($k),"PW falsch";
			};
		}
		print STDERR "\r... alle durch (".(0+@knd).").\n";
		return 0+@knd;
	}

	my $expp = sub {
		my($pp,$pseq,$ts);
		DoBinary {
			if($opp) {
				($pp,$ts) = DoFn("select pass,timestamp from passwort where kunde = $id and seq = $opp");
			} else {
				($pp,$pseq,$ts)= DoFn("select pass,seq,timestamp from passwort where kunde = $id order by seq desc limit 1");
			}
		};
		$pp = "" if $flag&4;

		if( content($pp) ) {
			ffehler {
				$pp = crypter $pp,$pw[$pw],1;
			} sub {
				undef $pw[$pw];
				undef $pp;
				goto fehler;
			};

			$neu[$pw]=0;
		} elsif($neu[$pw] and not $flag&1) {
			# Teste ob das Passwort woanders bereits OK ist
			my $xpp;
			DoBinary {
				$xpp = DoFn("select passwort.pass,kunde.id from passwort,kunde where passwort.kunde=kunde.id and kunde.pwklasse=$pw order by passwort.timestamp desc limit 1");
			};
			if(defined $xpp) {
				ffehler {
					print STDERR " Teste das Passwort...\n";
					$xpp = 1 if crypter $xpp,$pw[$pw],1 ne "";
				} sub {
					undef $pw[$pw];
					$xpp = 0;
				};
				return problem "Bitte Erinnerung auffrischen und nochmal probieren." unless $xpp;
			} else {
				# 
				my $ver = line_in("Nochmal das Passwort: ",1);
				return undef unless $ver ne "";
				if($ver ne $pw[$pw]) {
					undef $pw[$pw];
					return problem "Bitte Fingerübungen machen und nochmal probieren.";
				}
			}
		}

		if($flag & 1) {
			unless(defined $pp) {
				print "...no password data.\n";
				return undef;
			}

			my $lp = line_printer(1);
			if ( my @unterkunden = grep $_ != $id, unterkunden( $id, undef, 1 ) ) {
				my @unterkunden_mit_passwoertern;
				DoSelect { push @unterkunden_mit_passwoertern, shift }
				'SELECT DISTINCT kunde.name FROM passwort'
				  . ' JOIN kunde ON passwort.kunde = kunde.id WHERE '
				  . in_list( 'passwort.kunde', '', @unterkunden )
				  . ' ORDER BY kunde.name';

				if (@unterkunden_mit_passwoertern) {
					my $hinweis =
					    'BEACHTE: Für d'
					  . ( @unterkunden_mit_passwoertern == 1 ? 'en' : 'ie' )
					  . ' Unterkunden '
					  . aufzaehlung(@unterkunden_mit_passwoertern)
					  . ' sind ebenfalls Passwörter definiert.';
					print $Db::pr_fh "$hinweis\n", '=' x length $hinweis,
					  "\n\n";
				}
			}
			print $Db::pr_fh "Passwörter für Kunde #$id ".name_kunde($id)." (#".($opp||$pseq).", ".isotime($ts).")\n\n";
			print $Db::pr_fh $pp;
			line_print_end();
			system('clear') if $lp <= 2;
		} else {
			$pp = editor($pp);
			system('clear');
			return unless defined $pp;

			ffehler {
				$pp = crypter $pp,$pw[$pw],2;
			} sub {
				undef $pp;
				goto fehler;
			};

			$pseq = 1+$pseq;
			log_update("kunde","id",$id,undef,"passwort",undef,$pseq);
			DoBinary {
				Do("insert into passwort set kunde=$id, seq=$pseq, pass=${\qquote $pp}");
			};
		}
		$pseq;
	};
	if($flag & 1) {
		&$expp;
	} else {
		my $res = DoTrans { &$expp; };
		print STDERR "Fehler: $res\n" if defined $res && $res =~ /^-/;
	}
	$pw[$pw]=undef if $opp;
}

1;
