#!/usr/bin/perl
##!d:/Perl/bin/perl

BEGIN {
#use lib 'd:/Programs/Perl/lib';
#use lib '/home/tkamiya/bin/lib';
my $BaseDir = $ENV{'TkPerlDir'};
#print "\nBaseDir: $BaseDir\n";
@INC = ("$BaseDir/lib", "$BaseDir/VNL", "d:/Programs/Perl/lib", @INC);
}

use strict;
#use warnings;
use CGI::Carp qw(fatalsToBrowser);

use MyHTMLApplication;
use Crystal::VASP;

BEGIN {
#	$| = 1;
	open (STDERR, ">&STDOUT");
}

#===============================================
# 大域変数
#===============================================
my $ScriptCharCode = 'utf8';
my $FileSystemCharCode = 'sjis';

my $OutFile = "summary.html";
$OutFile = $ARGV[0] if(defined $ARGV[0]);
my $Target = ($ARGV[1] eq '')? '' : $ARGV[1];

my @ErrStrs = ("OK", "Not converged", "Terminated by unknown reason", "Structure relaxation not converged");

#===============================================
# Applicationオブジェクト作成
#===============================================
my $App = new MyHTMLApplication;
my $ret = $App->Initialize();
exit(-1) if($ret < 0);
#if(!defined $App->SetOutputMode("html:WriteBuffer")) {
#if(!defined $App->SetOutputMode("html")) {
if(!defined $App->SetOutputMode("html:WriteFile", undef, $OutFile)) {
	$App->print("Error: Can not write to [$OutFile].\n");
	exit;
}

$App->InitHTML();
$ret = &MakeVASPSummary($App, ".");
$App->EndHTML();

#$App->PrintBuffer(1);

exit($ret);

#===============================================
# Subroutines
#===============================================
sub GetLinkString
{
	my ($App, $key, $label, $GivenTarget, $dir, $filename, $path) = @_;

	if($key eq 'LinkToDirectory') {
		$path = Utils::MakePath($dir, $filename, '/', 0) if(!defined $path);
		return "<a href=\"$path\" target=\"$GivenTarget\">$label</a>";
	}
	if($key eq 'LinkToFile') {
		$path = Utils::MakePath($dir, $filename, '/', 0) if(!defined $path);
		return "<a href=\"$path\" target=\"$GivenTarget\">$label</a>";
	}
}

sub MakeVASPSummary
{
	my ($App, $RootDir) = @_;

	print("\nMakeSummaryHTML\n");

	$App->H2("Details for [$RootDir]\n");
	
	my @Dirs = $App->CollectDirs($App->pParams(), $RootDir, 
				["Original*", "original*", "0*", "1*", "2*", "3*", "4*", "5*", "6*", "7*", "8*", "9*", 
				 "MD*", "Relax*", "VCRelax*", "DFTSCF*", "SCF*", "DOS*", "Band*", "eDensity*",
				 "Phonopy", "Phonon", "IR", "Raman",
				 "."]);
	print("Dirs: ", join(@Dirs, ', '));
	$App->PrintRawHTML("<b>Directories</b>\n");
	$App->BeginItem(1);
	my @DirFileNames;
	for(my $i = 0 ; $i < @Dirs ; $i++) {
#print("Dir[$i]: $Dirs[$i]\n");
		$App->PrintItem($Dirs[$i]);
		my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($Dirs[$i]);
		$DirFileNames[$i] = $filename;
		
	}
	$App->EndItem(1);

	my $vasp = new VASP;
	my @INCARs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadINCARtoHash(Utils::MakePath($dir, 'INCAR', '/', 0));
						} );
	my @KPOINTSs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadKPOINTStoHash(Utils::MakePath($dir, 'KPOINTS', '/', 0));
						} );
	my @POTCARs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadPOTCARtoHash(Utils::MakePath($dir, 'POTCAR', '/', 0));
						} );
	my @POSCARs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadPOSCARtoHash($dir);
						} );
	my @OUTCARs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-d $dir);
							my $path = Utils::MakePath($dir, 'OUTCAR', '/', 0);
print "OUTCAR: $path\n";
							return {} if(!-f $path);
							my $hash = $vasp->ReadOUTCARtoHash($path);
print "  read $path [$hash->{TotCPUTime}][$hash->{AbortMessage}]\n";
							return $hash;
						} );
	my @Charges = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-d $dir);
							my $POTCARPath = Utils::MakePath($dir, 'POTCAR', '/', 0);
							return {} if(!-f $POTCARPath);
print "POTCAR: $POTCARPath\n";
							my %hash;
							$hash{nVEL}       = $vasp->GetTotalValenceElectrons($POTCARPath);
							$hash{NIONS}      = $vasp->GetNIONS($POTCARPath, 1);
#print "NI=$hash{NIONS}\n";
							$hash{defNBANDS}  = $vasp->EstimateDefaultNBANDS($POTCARPath);
							my ($pAtomName, $pSiteIndex, $pCharge, $pMagnetization, $pZVAL) = $vasp->GetFinalIonCharges($POTCARPath);
							my $s = '';
							for(my $i = 0 ; $i < @$pAtomName ; $i++) {
print "$i: $pAtomName->[$i]: Charge=$pCharge->[$i]: Mag=$pMagnetization->[$i]\n";
								my $Z = (defined $pCharge->[$i])?        sprintf(" Z=%5.2f", $pCharge->[$i])         : '';
								my $M = (defined $pMagnetization->[$i])? sprintf("   u=%5.3f", $pMagnetization->[$i]) : '';
								$s .= sprintf("$pAtomName->[$i]:$Z$M\n");
							}
							$hash{ChargeLines} = $s;
							return \%hash;
						} );
	my @BADERs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadBaderOuttoHash($dir);
						} );
	my @MADELUNGs = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-e $dir);
							return $vasp->ReadMadelungPotentialtoHash($dir);
						} );

	my $CompleteCorrectly = 0;
	for(my $i = 0 ; $i < @OUTCARs ; $i++) {
		next if($Dirs[$i] =~ /Original[^\/\\]*$/i);
		next if($Target ne '' and $Target ne $Dirs[$i]);

		my $p = $OUTCARs[$i];
		if($Dirs[$i] =~ /Relax$/i) {
			if($p->{RequiredAccuracyMessage} =~ /^\s*$/) {
				$CompleteCorrectly = 3;
				last;
			}
		}
		if($Dirs[$i] =~ /Relax\d$/i) {
			next;
		}
		if($p->{AbortMessage} !~ /is\s+reached/) {
#print "AM: $p->{AbortMessage} for $Dirs[$i]\n";
			$CompleteCorrectly = 1;
			last;
		}
		if($Dirs[$i] !~ /MD/i and $p->{TotCPUTime} eq '') {
print "$i: $Dirs[$i]: 150\n";
			$CompleteCorrectly = 2;
			last;
		}
	}
	my @ErrStrs = ("OK", "Not converged", "Terminated by unknown reason", "Structure relaxation not converged");
	if($CompleteCorrectly == 0) {
		$App->H3("\OK: Proccesses finished correctly.\n");
	}
	else {
		$App->H1("\nError: Proccess finished incorrectly with return code [$CompleteCorrectly:$ErrStrs[$CompleteCorrectly]].\n");
	}

	$App->H3("Input data\n");
	$App->BeginTable(1);
	$App->TableRow(["key", @DirFileNames], "<b>{text}</b>");
	foreach my $key (qw(SYSTEM ISPIN) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @INCARs ; $i++) {
			$App->TableCell($INCARs[$i]->{$key});
		}
	}
	foreach my $key (qw(PseudoPotential) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @POTCARs ; $i++) {
			my $s = $POTCARs[$i]->{$key};
			$s =~ s/(\s\S{1,2}\s)/<b>$1<\/b>/sg;
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	for(my $i = 0 ; $i < @INCARs ; $i++) {
		$INCARs[$i]->{defNBANDS} = $Charges[$i]->{defNBANDS};
	}
	foreach my $key (qw(ISTART ICHARG PREC EDIFF EDIFFG 
					 ENCUT defNBANDS NBANDS NELECT LREAL
					 METAGGA CMBJA CMBJB CMBJ LMAXTAU LMIXTAU
					 LSORBIT LNONCOLLINEAR LDAU LHFCALC
					 LMAXPAW LMAXMIX
					 NELM NSW
					 ISIF IBRION ISYM POTIM SMASS TEBEG TEEND PSTRESS 
					 RWIGS ISMEAR SIGMA EMIN EMAX NEDOS) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @INCARs ; $i++) {
			$App->TableCell($INCARs[$i]->{$key});
		}
	}
	foreach my $key (qw(KPOINTS) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @KPOINTSs ; $i++) {
			my $s = $KPOINTSs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(SumChemicalComposition ChemicalComposition FormulaUnit Latt Volume Density AtomSites) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @POSCARs ; $i++) {
			my $s = $POSCARs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(nAtomSite) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @POSCARs ; $i++) {
			my $s = $POSCARs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(nVEL NIONS ) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @Charges ; $i++) {
			my $s = $Charges[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
#print"$key: s=$s\n";
			$App->TableCell($s);
		}
	}
	$App->EndTable();

	$App->H3("Output data\n");
	$App->BeginTable(1);
	$App->TableRow(["key", @DirFileNames], "<b>{text}</b>");
	foreach my $key (qw(StaticSymmetry DynamicSymmetry ConstrainedSymmetry
					GGA LHFCALC PRECFOCK HFSCREEN AEXX ALDAX AGGAX ALDAC AGGAC
						ENCUT NBANDS
						NKPTS NEDOS NIONS LDIM LMDIM NPLWV CurrNGXYZ RecommendNGXYZ
						TEIN TEBEG TEEND POMASS
						NELECT NUPDOWN
						IALGO LDIAG IMIX AMIX TIME
						LSECVAR IDIPOL LDIPOL LVHAR LVTOT
						TOTEN TOTENwoS TOTENwoSlim
						EF 
						AbortMessage RequiredAccuracyMessage
						TotCPUTime UserTime SystemTime ElapsedTime) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @OUTCARs ; $i++) {
			my $s = $OUTCARs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(Latt Volume Density AtomSites) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @POSCARs ; $i++) {
			my $s = $POSCARs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(ZVAL) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @OUTCARs ; $i++) {
			my $s = $OUTCARs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(nVEL ChargeLines) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @Charges ; $i++) {
			my $s = $Charges[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key (qw(BaderCharges) ) {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @BADERs ; $i++) {
			my $s = $BADERs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}
	foreach my $key ('MP(Formal Z)', 'MP(Bader Z)') {
		$App->BeginTableRow();
		$App->TableCell("<b>$key</b>");
		for(my $i = 0 ; $i < @MADELUNGs ; $i++) {
			my $s = $MADELUNGs[$i]->{$key};
			$s =~ s/[\r\n]/<br>\n/sg;
			$App->TableCell($s);
		}
	}

	$App->EndTable();

	$App->HR();
	$App->H3("Representative files under [$RootDir]\n");
	$App->SearchDirectory($App->pParams(), "\\.(cif|xsf|ps|pdf|csv|txt|out)\$", $RootDir,
			sub {
				my ($App, $key, $HitCountInDir, $path, $dir, $filename) = @_;
				if($key =~ /^NotHit/) {
				}
				elsif($key =~ /^EnterDir/) {
					my $LinkStr = &GetLinkString($App, "LinkToDirectory", $dir, "_blank", $dir);
					$App->PrintRawHTML("<b>$LinkStr</b><br>\n");
					$App->BeginItem(0);
				}
				elsif($key =~ /^ExitDir/) {
					$App->EndItem();
				}
				else {
					my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($path);
					my $wtime = Utils::BuildDateString(Utils::GetWriteDate($path));
					my $size = int(Utils::GetFileSize($path) / 1024);
					my $LinkStr = &GetLinkString($App, "LinkToFile", $filename, "_blank", $path);
					$App->PrintItem("$LinkStr ($size kB) $wtime<br>\n");
				}
			},
			0, 2, undef, $ScriptCharCode, $FileSystemCharCode);

	my $CompleteCorrectly = 0;
	for(my $i = 0 ; $i < @OUTCARs ; $i++) {
		next if($Dirs[$i] =~ /Original[^\/\\]*$/i);
		next if($Target ne '' and $Target ne $Dirs[$i]);

		my $p = $OUTCARs[$i];
		if($Dirs[$i] =~ /Relax$/i) {
			if($p->{RequiredAccuracyMessage} =~ /^\s*$/) {
#print "dir: $Dirs[$i]\n";
print "RequiredAccuracyMessage is not found in [$Dirs[$i]]. Return 3\n";
				$CompleteCorrectly = 3;
				last;
			}
		}
		elsif($Dirs[$i] =~ /Relax\d$/i) {
			if($p->{RequiredAccuracyMessage} =~ /^\s*$/) {
print "RequiredAccuracyMessage is not found in [$Dirs[$i]]. Return 3\n";
#print "dir: $Dirs[$i]\n";
				$CompleteCorrectly = 3;
#				last;
			}
			next;
		}
		elsif($Dirs[$i] =~ /Phonon$/i) {
		}
		elsif($Dirs[$i] =~ /Phonopy$/i) {
		}
		elsif($Dirs[$i] =~ /IR$/i) {
		}
		elsif($Dirs[$i] =~ /Raman$/i) {
		}
		elsif($Dirs[$i] =~ /MD/i) {
		}
		elsif($Dirs[$i] =~ /eDensity/i) {
		}
		else {
			if($p->{AbortMessage} ne '' and $p->{AbortMessage} !~ /is\s+reached/) {
print "AbortMessage is [$p->{AbortMessage}] in [$Dirs[$i]]. Return 1\n";
				$CompleteCorrectly = 1;
				last;
			}
			if($p->{TotCPUTime} eq '') {
#print "$i: $Dirs[$i]: 290\n";
print "TotCPUTime is [$p->{TotCPUTime}] in [$Dirs[$i]]. Return 2\n";
				$CompleteCorrectly = 2;
				last;
			}
		}
	}
#print "ret: $CompleteCorrectly\n";
	return $CompleteCorrectly;
}

