#!/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 Cwd;

use Deps;
use Utils;
use MyHTMLApplication;
use Crystal::VASP;
use Sci::ChemicalReaction;

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

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

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

my @OutputTerms = (
	FileBody               => 'Source',
	Compound               => 'Compound',
	SortedComposition      => 'SortedComposition/Z',
	SumChemicalComposition => 'Composition',
	Type                   => 'Type',
	FormulaUnit            => 'Z',
#	'Position(16,x)'       => 'x(Se)',
#	'Position(16,y)'       => 'y(Se)',
#	'Position(16,z)'       => 'z(Se)',
	TOTEN                  => 'Etot',
	'Etot/mol(SCF)'        => 'Emol',
	'EF(SCF)'              => 'EF(SCF)',
	'EF(DOS)'              => 'EF(DOS)',
	VBM                    => 'EVBM',
	CBM                    => 'ECBM',
	Eg                     => 'Eg',
	Density                => 'Density',
	a                      => 'a',
	b                      => 'b',
	c                      => 'c',
	Volume                 => 'V',
	'WSZ(0)'               => 'WSZ(A)',
	'WSZ(2)'               => 'WSZ(B)',
	'BZ(0)'                => 'BZ(A)',
	'BZ(1)'                => 'BZ(B)',
	'MPF(0)'               => 'MPF(A)',
	'MPF(1)'               => 'MPF(B)',
	'MPB(0)'               => 'MPB(A)',
	'MPB(1)'               => 'MPB(B)',
	PseudoPotential        => 'PP',
	PREC                   => 'PREC',
	'aKmin(SCF)'           => 'aK(SCF)',
	'aKmin(VCRelax)'       => 'aK(VCRelax)',
	EDIFF                  => 'EDIFF',
	EDIFFG                 => 'EDIFFG',
	NBANDS                 => 'NBANDS',
	ISPIN                  => 'ISPIN',
	NUPDOWN                => 'NUPDOWN',
	LDAU                   => 'LDAU',
	LDAUU                  => 'U',
	LDAUJ                  => 'J',
	ISMEAR                 => 'ISMEAR',
	SIGMA                  => 'SIGMA',
	Status                 => 'Status',
	Ref                    => 'Ref',
	);


#===============================================
# Applicationオブジェクト作成
#===============================================
my $App = new MyHTMLApplication;
my $ret = $App->Initialize();
exit(-1) if($ret < 0);

$App->SetOutputMode("console");

#my $DOSDir = "I:/Functional/Si/Si-HF/DOS";
#my ($EF, $VBM, $CBM, $Eg) = &ReadFromDOSOUTCAR(Deps::MakePath($DOSDir, 'OUTCAR', 0));
#print "$EF, $VBM, $CBM, $Eg\n";
#exit;

my $nLevel = 3;
my @Dirs;
#my @Dirs = sort { $a cmp $b; } glob("*");
@Dirs = Utils::SearchFilesRecursive2(".", "*", $nLevel, \@Dirs, 1,
			sub { 
				my ($path) = @_;
				return 0 if(!-d $path);
print "path[$path]\n";
				if($path =~ /\.nosearch[\\\/]/i or $path =~ /\.nosearch$/i) {
#print "  Skip\n";
					return 0;
				}

				my $SCFDir = Deps::MakePath($path, "SCF", 0);
#				print "dir: $path [$SCFDir]\n"; 
				if(-d $SCFDir) {
#print "  Registered\n";
					return 1;
				}
#print "  Skip2\n";
				return 0;
			},
			SearchDir => 1,
#			Debug     => 1,
			);
#exit;
#for(my $i= 0 ; $i < @Dirs ; $i++) {
#	print "$i: $Dirs[$i]\n";
#}
#exit;

my $R = new ChemicalReaction;

my $out = new JFile;
if(!$out->Open($OutFile, "w")) {
	$App->print("Error: Can not write to [$OutFile].\n");
	exit;
}

for(my $i = 0 ; $i < @OutputTerms ; $i += 2) {
	if($i == 0) {
		$out->print($OutputTerms[$i+1]);
	}
	else {
		$out->print(',' . $OutputTerms[$i+1]);
	}
}
$out->print("\n");
#$out->print("Source,Compound,SortedComposition/Z,Composition,Type,"
#		   ."Z,Etot,Emol,EF(SCF),"
#		   ."EF(DOS),EVBM,ECBM,Eg,"
#		   ."Density,a,b,c,V,"
#		   ."PP,"
#		   ."PREC,aK(SCF),aK(VCRelax),EDIFF,EDIFFG,NBANDS,"
#		   ."ISPIN,NUPDOWN,LDAU,U,J,"
#		   ."ISMEAR,SIGMA,"#		   ."Status,Ref\n");

print("\nMakeSummaryHTML\n");
#print "nDirs = ", scalar @Dirs, "\n";
for(my $i = 0 ; $i < @Dirs ; $i++) {
#print "dir[$i]: $Dirs[$i]\n";
	next if(!-d $Dirs[$i]);
	next if($Dirs[$i] =~ /junk/i);
	
	my $SCFDir = Deps::MakePath($Dirs[$i], "SCF", 0);
	next if(!-d $SCFDir);

	$App->print("\n$i: $Dirs[$i]\n");
	my $ret = &MakeVASPSummary($App, $out, $Dirs[$i]);
}

$out->Close();

exit;

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

	my ($drive, $directory, $filename, $ext1, $lastdir, $filebody) = Deps::SplitFilePath($RootDir);

	my $VCRelaxDir = Deps::MakePath($RootDir, "VCRelax", 0);
	my $SCFDir     = Deps::MakePath($RootDir, "SCF", 0);
	my $DOSDir     = Deps::MakePath($RootDir, "DOS", 0);

	my $vasp = new VASP;
	my $INCARHash          = $vasp->ReadINCARtoHash   (Utils::MakePath($SCFDir,     'INCAR', '/', 0));
	my $KPOINTSHash        = $vasp->ReadKPOINTStoHash (Utils::MakePath($SCFDir,     'KPOINTS', '/', 0));
	my $VCRelaxKPOINTSHash = $vasp->ReadKPOINTStoHash (Utils::MakePath($VCRelaxDir, 'KPOINTS', '/', 0));
	my $POTCARPath         = Utils::MakePath($SCFDir,     'POTCAR', '/', 0);
	my $POTCARHash         = $vasp->ReadPOTCARtoHash  ($POTCARPath);
	my $POSCARHash         = $vasp->ReadPOSCARtoHash  (Utils::MakePath($SCFDir,     'POSCAR', '/', 0));
	my $SCFOUTCARHash      = $vasp->ReadOUTCARtoHash  (Utils::MakePath($SCFDir,     'OUTCAR', '/', 0));
	my $VCROUTCARHash      = $vasp->ReadOUTCARtoHash  (Utils::MakePath($VCRelaxDir, 'OUTCAR', '/', 0));
	my $BaderHash          = $vasp->ReadBaderOuttoHash(Utils::MakePath($DOSDir,     'Bader.out', '/', 0));
	my $MPHash             = $vasp->ReadMadelungPotentialtoHash(Utils::MakePath($DOSDir, 'LDEnergy.out', '/', 0));

	my $nVEL       = $vasp->GetTotalValenceElectrons($POTCARPath);
	my $NIONS      = $vasp->GetNIONS($POTCARPath, 1);
	my $defNBANDS  = $vasp->EstimateDefaultNBANDS($POTCARPath);
	my ($pAtomName, $pSiteIndex, $pCharge, $pMagnetization, $pZVAL) = $vasp->GetFinalIonCharges($POTCARPath);

	my @WSCharges;
	my @Charges = $App->ReadDirsToHash($App->pParams(), \@Dirs, 
						sub { 
							my ($dir) = @_;
							return {} if(!-d $dir);
							my $POTCARPath = Utils::MakePath($SCFDir, 'POTCAR', '/', 0);
							return {} if(!-f $POTCARPath);
print "POTCAR: $POTCARPath\n";
							my %hash;
							$hash{nVEL}  = $nVEL;
							$hash{NIONS} = $NIONS;
							$hash{defNBANDS} = $defNBANDS;
#							my $s = '';
							if($pCharge and $pMagnetization) {
								for(my $i = 0 ; $i < @$pAtomName ; $i++) {
print "$i: $pAtomName->[$i]: Charge=$pCharge->[$i]: Mag=$pMagnetization->[$i]\n";
									my $Z = (defined $pCharge->[$i])?        $pCharge->[$i] : '';
#									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");
									$WSCharges[$i] = {
										iSite         => $pSiteIndex->[$i],
										AtomName      => $pAtomName->[$i],
										Charge        => $Z,
										Magnetization => $M,
										};
								}
							}

#							$hash{ChargeLines} = $s;
							return \%hash;
						} );

	my $Status = '';
	if(-d $VCRelaxDir and $VCROUTCARHash->{RequiredAccuracyMessage} =~ /^\s*$/) {
		$Status = 'Relaxation not converged(1)';
	}
	elsif(-d $VCRelaxDir and $VCROUTCARHash->{AbortMessage} !~ /is\s+reached/) {
		$Status = 'Relaxation not converged(2)';
	}
	elsif(-d $VCRelaxDir and $VCROUTCARHash->{TotCPUTime} eq '') {
		$Status = 'VCR aborted(1)';
	}
	elsif($SCFOUTCARHash->{AbortMessage} =~ /^\s*$/) {
		$Status = 'SCF not converged(1)';
	}
	elsif($SCFOUTCARHash->{TotCPUTime} eq '') {
		$Status = 'SCF aborted(1)';
	}
	my ($EF, $VBM, $CBM, $Eg) = VASP->new()->ReadEgFromDOSOUTCAR(Deps::MakePath($DOSDir, 'OUTCAR', 0));

	$App->print("ISPIN=$INCARHash->{ISPIN}\n");
	$App->print("PREC=$INCARHash->{PREC}\n");
	$App->print("EDIFF=$INCARHash->{EDIFF}\n");
	$App->print("EDIFFG=$INCARHash->{EDIFFG}\n");
	$App->print("LDAU=$INCARHash->{LDAU}\n");
	$App->print("LDAUTYPE=$INCARHash->{LDAUTYPE}\n");
	$App->print("LDAUU=$INCARHash->{LDAUU}\n");
	$App->print("LDAUJ=$INCARHash->{LDAUJ}\n");
	$App->print("ISMEAR=$INCARHash->{ISMEAR}\n");
	$App->print("SIGMA=$INCARHash->{SIGMA}\n");
	$POTCARHash->{PseudoPotential} =~ s/ .*$//s;
	$App->print("PseudoPotential=$POTCARHash->{PseudoPotential}\n");

	my $pAtomSite = $POSCARHash->{pAtomSite};
	my $pAtomType = $POSCARHash->{pAtomSite};

	$VCRelaxKPOINTSHash->{KPOINTS} =~ s/^[^\n]*\n[^\n]*\n[^\n]*\n//m;
	$VCRelaxKPOINTSHash->{KPOINTS} =~ s/\n.*$//m;
	Utils::DelSpace($VCRelaxKPOINTSHash->{KPOINTS});
	my @nKVCRelax = Utils::Split("\\s+", $VCRelaxKPOINTSHash->{KPOINTS});

	$KPOINTSHash->{KPOINTS} =~ s/^[^\n]*\n[^\n]*\n[^\n]*\n//m;
	$KPOINTSHash->{KPOINTS} =~ s/\n.*$//m;
	Utils::DelSpace($KPOINTSHash->{KPOINTS});
	my @nK = Utils::Split("\\s+", $KPOINTSHash->{KPOINTS});

	$App->print("KPOINTS=$KPOINTSHash->{KPOINTS}\n");
	$App->print("ISPIN=$INCARHash->{ISPIN}\n");
	$App->print("Etot=$SCFOUTCARHash->{TOTEN}\n");
	$App->print("EF(SCF)=$SCFOUTCARHash->{EF}\n");
	$App->print("EF(DOS)=$EF\n");
	$App->print("EVBM(DOS)=$VBM\n");
	$App->print("ECBM(DOS)=$CBM\n");
	$App->print("Eg(DOS)=$Eg\n");
	$App->print("SumChemicalComposition=$POSCARHash->{SumChemicalComposition}\n");
	$App->print("ChemicalComposition=$POSCARHash->{ChemicalComposition}\n");
	$App->print("FormulaUnit=$POSCARHash->{FormulaUnit}\n");

	$POSCARHash->{Latt} =~ s/\n/,/g;
	my @latt = Utils::Split(",+", $POSCARHash->{Latt});

	my @aKVCRelax = ($latt[0]*$nKVCRelax[0], $latt[1]*$nKVCRelax[1], $latt[2]*$nKVCRelax[2]);
	my ($aKminVCRelax, $aKmaxVCRelax) = Utils::CalMinMax(\@aKVCRelax);
	$aKminVCRelax = sprintf("%4.1f", $aKminVCRelax);

	my @aK = ($latt[0]*$nK[0], $latt[1]*$nK[1], $latt[2]*$nK[2]);
	my ($aKmin, $aKmax) = Utils::CalMinMax(\@aK);
	$aKmin = sprintf("%4.1f", $aKmin);

	$App->print("Latt=$POSCARHash->{Latt}\n");
	$App->print("aKMax=$aKmin-$aKmax\n");
	$App->print("Volume=$POSCARHash->{Volume}\n");
	$App->print("Density=$POSCARHash->{Density}\n");

	my $Ref = Deps::MakePath(cwd(), $RootDir, 0);
	$Ref =~ s/$ENV{HOME}//;
	my $Eavrg    = $SCFOUTCARHash->{TOTEN} / $POSCARHash->{FormulaUnit};
	my $Compound = $POSCARHash->{ChemicalComposition};
#	my $Compuond = $POSCARHash->{SumChemicalComposition};
	my $SortedComposition = $R->SortChemicalFormula($POSCARHash->{ChemicalComposition});
	$Compound =~ s/\s//g;
	$Status .= " / SCFWarning:$SCFOUTCARHash->{Warning}" if($SCFOUTCARHash->{Warning} ne '');
	$Status .= " / VCRWarning:$VCROUTCARHash->{Warning}" if($VCROUTCARHash->{Warning} ne '');

	my %v = (
		FileBody         => $filebody,
		Compound         => $Compound,
		SortedComposition      => $SortedComposition,
		SumChemicalComposition => $POSCARHash->{SumChemicalComposition},
		FormulaUnit      => $POSCARHash->{FormulaUnit},
		TOTEN            => $SCFOUTCARHash->{TOTEN},
		'Etot/mol(SCF)'  => $Eavrg,
		'EF(SCF)'        => $SCFOUTCARHash->{EF},
		'EF(DOS)'        => $EF,
		VBM              => $VBM,
		CBM              => $CBM,
		Eg               => $Eg,
		Density          => $POSCARHash->{Density},
		a                => $latt[0],
		b                => $latt[1],
		c                => $latt[2],
		alpha            => $latt[3],
		beta             => $latt[4],
		gamma            => $latt[5],
		Volume           => $POSCARHash->{Volume},
		PseudoPotential  => $POTCARHash->{PseudoPotential},
		PREC             => $INCARHash->{PREC},
		'aKmin(SCF)'     => $aKmin,
		'aKmax(SCF)'     => $aKmax,
		'aKmin(VCRelax)' => $aKminVCRelax,
		EDIFF            => $INCARHash->{EDIFF},
		EDIFFG           => $INCARHash->{EDIFFG},
		NBANDS           => $INCARHash->{NBANDS},
		ISPIN            => $INCARHash->{ISPIN},
		NUPDOWN          => $INCARHash->{NUPDOWN},
		LDAU             => $INCARHash->{LDAU},
		LDAUU            => $INCARHash->{LDAUU},
		LDAUJ            => $INCARHash->{LDAUJ},
		ISMEAR           => $INCARHash->{ISMEAR},
		SIGMA            => $INCARHash->{SIGMA},
		Status           => $Status,
		Ref              => $Ref,
		);
	for(my $i = 0 ; $i < @$pAtomSite ; $i++) {
		my ($x, $y, $z) = $pAtomSite->[$i]->Position();
		$v{"Position($i,x)"} = $x;
		$v{"Position($i,y)"} = $y;
		$v{"Position($i,z)"} = $z;
	}
	if($BaderHash) {
		my $pAtomType = $BaderHash->{pAtomType};
#		$pAtomSite = $BaderHash->{pAtomSite};
		if($pAtomSite) {
			for(my $i = 0 ; $i < @$pAtomType ; $i++) {
				$v{"BZ($i)"} = $pAtomType->[$i]{BaderCharge};
			}
		}
	}
	for(my $i = 0 ; $i < @$pAtomType ; $i++) {
		$v{"WSZ($i)"} = $WSCharges[$i]{Charge} if($WSCharges[$i]);
	}

	my $pMP    = $MPHash->{pFormalCharge};
	if($pMP) {
		$pAtomSite = $pMP->{pAtomSite};
		if($pAtomSite) {
			for(my $i = 0 ; $i < @$pAtomSite ; $i++) {
				$v{"MPF($i)"} = $pAtomSite->[$i]{MP};
			}
		}
	}
	$pMP       = $MPHash->{pBaderCharge};
	if($pMP) {
		$pAtomSite = $pMP->{pAtomSite};
		if($pAtomSite) {
			for(my $i = 0 ; $i < @$pAtomSite ; $i++) {
				$v{"MPB($i)"} = $pAtomSite->[$i]{MP};
			}
		}
	}

	for(my $i = 0 ; $i < @OutputTerms ; $i += 2) {
		my $key = $OutputTerms[$i];
		if($i == 0) {
			$out->print($v{$key});
		}
		else {
			$out->print(',' . $v{$key});
		}
	}
	$out->print("\n");

#	$out->print("$filebody,$Compound,$SortedComposition,$POSCARHash->{SumChemicalComposition},,"
#			   ."$POSCARHash->{FormulaUnit},$SCFOUTCARHash->{TOTEN},$Eavrg,$SCFOUTCARHash->{EF},"
#			   ."$EF,$VBM,$CBM,$Eg,"
#			   ."$POSCARHash->{Density},$latt[0],$latt[1],$latt[2],$POSCARHash->{Volume},"
#			   ."$POTCARHash->{PseudoPotential},"
#			   ."$INCARHash->{PREC},$aKmin,$aKminVCRelax,$INCARHash->{EDIFF},$INCARHash->{EDIFFG},"
#			   ."$INCARHash->{NBANDS},"
#			   ."$INCARHash->{ISPIN},$INCARHash->{NUPDOWN},$INCARHash->{LDAU},$INCARHash->{LDAUU},$INCARHash->{LDAUJ},"
#			   ."$INCARHash->{ISMEAR},$INCARHash->{SIGMA},"
#			   ."$Status,$Ref\n");

	return 1;
}
