#!/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", "VCRelax*", "SCF*", "DOS*", "Band*", "eDensity*"]);
	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);
							my ($pAtomName, $pSiteIndex, $pCharge, $pMagnetization) = $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 $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);
		}
	}
	foreach my $key (qw(ISTART ICHARG PREC EDIFF EDIFFG 
					 LSORBIT LNONCOLLINEAR LDAU LHFCALC
					 LMAXPAW LMAXMIX
					 NELM NSW
					 NELECT NBANDS
					 ISIF IBRION ISYM POTIM SMASS TEBEG TEEND PSTRESS 
					 RWIGS ISMEAR SIGMA EMIN EMAX NEDOS LREAL) ) {
		$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);
		}
	}
	$App->EndTable();

	$App->H3("Output data\n");
	$App->BeginTable(1);
	$App->TableRow(["key", @DirFileNames], "<b>{text}</b>");
	foreach my $key (qw(StaticSymmetry DynamicSymmetry ConstrainedSymmetry
						NKPTS NEDOS NIONS LDIM LMDIM NPLWV CurrNGXYZ RecommendNGXYZ
						TEIN TEBEG TEEND POMASS  ZVAL
						NELECT NUPDOWN
						IALGO LDIAG IMIX TIME
						LSECVAR IDIPOL LDIPOL
						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(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(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);
		}
	}
	$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";
				$CompleteCorrectly = 3;
				last;
			}
		}
		if($Dirs[$i] =~ /Relax\d$/i) {
			if($p->{RequiredAccuracyMessage} =~ /^\s*$/) {
#print "dir: $Dirs[$i]\n";
#				$CompleteCorrectly = 3;
#				last;
			}
			next;
		}
		if($Dirs[$i] !~ /MD/i and $Dirs[$i] !~ /eDensity/i) {
			if($p->{AbortMessage} !~ /is\s+reached/) {
				$CompleteCorrectly = 1;
				last;
			}
			if($p->{TotCPUTime} eq '') {
print "$i: $Dirs[$i]: 290\n";
				$CompleteCorrectly = 2;
				last;
			}
		}
	}
#print "ret: $CompleteCorrectly\n";
	return $CompleteCorrectly;
}

