#!/usr/bin/perl

use strict;

use lib 'd:/Programs/Perl/lib';
use lib "$ENV{TkPerlDir}/lib";

use Utils;
use JFile;
use CSV;
use MyApplication;

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

#===============================================
# Global variables
#===============================================
my $InFile     = "EffectiveMassBand.csv";
my $OutCBMFile = "SummaryCBEffectiveMass.csv";
my $OutVBMFile = "SummaryVBEffectiveMass.csv";
my $torE = 0.1;

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

#$App->SetLF("<br>\n");
#$App->SetPrintCharCode("sjis");
#$App->SetDebug($Debug);
$App->SetDeleteHTMLFlag(1);

#==========================================
# コマンドラインオプション読み込み
#==========================================
#$App->AddArgument("--Action", "--Action=[]", '');
$App->AddArgument("--DieIfNotExist", "--DieIfNotExist=[0|1] (Def:1)", 1);
exit 1 if($App->ReadArgs(1, "sjis", 0) != 1);
my $Args = $App->Args();

my $DieIfNotExist = $App->GetGetArg('DieIfNotExist', 1);
my $Root          = $App->GetGetArg(0);
$Root = '.' if(!defined $Root);
my $dirmask       = $App->GetGetArg(1);
$dirmask = '*' if(!defined $dirmask);

print "DieIfNotExist: [$DieIfNotExist]\n";
print "RootDir: [$Root]\n";
print "DirMask: [$dirmask]\n";

#===============================================
# Collect dirs
#===============================================
my $nLevel = 3;
my @Dirs;
@Dirs = Utils::SearchFilesRecursive2($Root, $dirmask, $nLevel, \@Dirs, 1,
			sub { 
				my ($path) = @_; 
#				print "dir: $path\n"; 
				return 0 if($path =~ /\.nosearch/i);
				return 1 if(-d Deps::MakePath($path, "BandX", 0));
			},
			SearchDir => 1,
			);
#for(my $i= 0 ; $i < @Dirs ; $i++) {
#	print "$i: $Dirs[$i]\n";
#}
#exit;

#===============================================
# Open Output InFile
#===============================================
my $cout = JFile->new($OutCBMFile, 'w') or die "$!: Can not write to [$OutCBMFile].\n";
my $vout = JFile->new($OutVBMFile, 'w') or die "$!: Can not write to [$OutVBMFile].\n";
$cout->print("Source");
$vout->print("Source");
for(my $i = 1 ; $i <= 10 ; $i++) {
	$cout->print(",k[$i],kdir[$i],E[$i],me*[$i]");
	$vout->print(",k[$i],kdir[$i],E[$i],mh*[$i]");
}
$cout->print("\n");
$vout->print("\n");

for(my $i = 0 ; $i < @Dirs ; $i++) {
	next if(!-d $Dirs[$i]);
	next if($Dirs[$i] =~ /junk/i);

	my $BandFile = Deps::MakePath($Dirs[$i], $InFile, 0);
	next if(!-f $BandFile);

print("$i: $BandFile..\n");
	my $pInf = &ReadEffectiveMasses($BandFile);
	next if(!$pInf);

	my $pVBInf = $pInf->{pVBInf};
	my $pCBInf = $pInf->{pCBInf};
#ik, k, kdir, E, me
	$cout->print("$pInf->{Source}");
	$vout->print("$pInf->{Source}");
	for(my $i = 0 ; $i < @$pVBInf ; $i++) {
		$vout->print(",$pVBInf->[$i]{k},$pVBInf->[$i]{kdir},$pVBInf->[$i]{E},$pVBInf->[$i]{me}");
	}
	for(my $i = 0 ; $i < @$pCBInf ; $i++) {
		$cout->print(",$pCBInf->[$i]{k},$pCBInf->[$i]{kdir},$pCBInf->[$i]{E},$pCBInf->[$i]{me}");
	}
	$cout->print("\n");
	$vout->print("\n");
}
$vout->Close();
$cout->Close();

exit;


#===============================================
# Subroutines
#===============================================
sub ReadEffectiveMasses
{
	my ($infile) = @_;

	my %inf;
	my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($infile);
	$inf{Source} = $lastdir;
#print "l:[$lastdir]\n";
#exit;

	my $csv = new CSV;
	if(!$csv->Read($infile, 0)) {
		print "Error: $!: Can not read [$infile].\n";
		die if($DieIfNotExist);
		return 0;
	}

	$csv->Close();

	my $pLabelArray = $csv->LabelArray();
	my $pDA         = $csv->DataArray();
	my $nDataRow    = @$pDA;
	my $pX          = $pDA->[0];
	my $nData       = @$pX;
#print "la: $pLabelArray\n";
print("  nDataRow: $nDataRow\n");
print("  nData   : $nData\n");

#===============================================
# Main routine
#===============================================
#kx,ky,kz,k,EVBM-2(eV),EVBM-1(eV),EVBM(eV),ECBM(eV),ECBM+1(eV),
#d2EVBM(-2)/dE2,d2EVBM(-1)/dE2,d2EVBM/dE2,d2ECBM/dE2,d2ECBM(+1)/dE2,
#mh*(-2),mh*(-1),mh*,me*,me*(+1)
	my ($iEVBM, $iECBM, $imh, $ime);
	for(my $i = 0 ; $i < $nDataRow ; $i++) {
		if($pLabelArray->[$i] eq 'EVBM(eV)') {
			$iEVBM = $i;
		}
		elsif($pLabelArray->[$i] eq 'ECBM(eV)') {
			$iECBM = $i;
		}
		elsif($pLabelArray->[$i] eq 'mh*') {
			$imh = $i;
		}
		elsif($pLabelArray->[$i] eq 'me*') {
			$ime = $i;
		}
	}

#print "\n";
#print "$pLabelArray->[0], $pLabelArray->[4], $pLabelArray->[5], \n";
for(my $i = 0 ; $i < $nData ; $i++) {
	print "$i: kx=$pDA->[0][$i], E1=$pDA->[4][$i], E2=$pDA->[5][$i], \n";
}

print "\n";
print "iEVBM=$iEVBM\n";
print "iECBM=$iECBM\n";
print "imh  =$imh\n";
print "ime  =$ime\n";

	my ($EVBM, $ikEVBM);
	my ($ECBM, $ikECBM);
	for(my $i = 0 ; $i < $nData ; $i++) {
		next if($pDA->[$iEVBM][$i] eq '');

#print "i=$i: EVBM=$pDA->[$i][$iEVBM]\n";
		if(!defined $EVBM or $EVBM < $pDA->[$iEVBM][$i]) {
			$ikEVBM = $i;
			$EVBM = $pDA->[$iEVBM][$i];
		}
		if(!defined $ECBM or $ECBM > $pDA->[$iECBM][$i]) {
			$ikECBM = $i;
			$ECBM = $pDA->[$iECBM][$i];
		}
	}
print "\n";
print "VBM: ik=$ikEVBM k=($pDA->[0][$ikEVBM], $pDA->[1][$ikEVBM], $pDA->[2][$ikEVBM]) EVBM=$EVBM eV\n";
print "CBM: ik=$ikECBM k=($pDA->[0][$ikECBM], $pDA->[1][$ikECBM], $pDA->[2][$ikECBM]) ECBM=$ECBM eV\n";

	my (@EVBM, @ikEVBM);
	my $cVBM = 0;
	my (@ECBM, @ikECBM);
	my $cCBM = 0;
	for(my $i = 0 ; $i < $nData ; $i++) {
		next if($pDA->[$iEVBM][$i] eq '');

#print "i=$i: EVBM=$pDA->[$iEVBM][$i]\n";
		if($EVBM-$torE < $pDA->[$iEVBM][$i]) {
			$ikEVBM[$cVBM] = $i;
			$EVBM[$cVBM]   = $pDA->[$iEVBM][$i];
			$cVBM++;
		}
		if($ECBM+$torE > $pDA->[$iECBM][$i]) {
			$ikECBM[$cCBM] = $i;
			$ECBM[$cCBM]   = $pDA->[$iECBM][$i];
			$cCBM++;
		}
	}

print "\n";
	my (@CBInf, @VBInf);
	my ($cCB, $cVB) = (0, 0);
	for(my $i = 0 ; $i < $cVBM ; $i++) {
		my $ikEVBM = $ikEVBM[$i];
#print "ikEVBM=$ikEVBM\n";
		if($ikEVBM+1 == $ikEVBM[$i+1] and $pDA->[$iEVBM][$ikEVBM] < $pDA->[$iEVBM][$ikEVBM+1]) {
			next;
		}
		elsif($ikEVBM-1 == $ikEVBM[$i-1] and $pDA->[$iEVBM][$ikEVBM] < $pDA->[$iEVBM][$ikEVBM-1]) {
			next;
		}

		my $i1;
		if($pDA->[2][$ikEVBM+1] ne '') {
			for(my $ik = $ikEVBM+1 ; $ik < $nData ; $ik++) {
#print "ik=$ik: $pDA->[2][$ik] \n";
				last if($pDA->[2][$ik] eq '');
				$i1 = $ik;
			}
		}
		else {
			for(my $ik = $ikEVBM-1 ; $ik >= 0 ; $ik--) {
				last if($pDA->[2][$ik] eq '');
				$i1 = $ik;
			}
		}
#print "i1=$i1\n";
		my ($kx0, $ky0, $kz0) = ($pDA->[0][$ikEVBM], $pDA->[1][$ikEVBM], $pDA->[2][$ikEVBM]);
		my ($kx1, $ky1, $kz1) = ($pDA->[0][$i1],     $pDA->[1][$i1],     $pDA->[2][$i1]);
		for(my $iE = $iEVBM ; $iE >= 0 ; $iE--) {
			last if($pLabelArray->[$iE] !~ /EVBM/i);
			next if($EVBM-$torE > $pDA->[$iE][$ikEVBM]);

			my $E  = $pDA->[$iE][$ikEVBM];
			my $me = $pDA->[$imh-($iEVBM-$iE)][$ikEVBM];
printf "VBM: ik=%03d k=($kx0,$ky0,$kz0)->($kx1,$ky1,$kz1) E=$E eV  m*=$me\n", $ikEVBM;
	
			$VBInf[$cVB] = {
				ik   => $ikEVBM,
				k    => "$kx0 $ky0 $kz0",
				kdir => "$kx1 $ky1 $kz1",
				E    => $E,
				me   => $me,
				};
			$cVB++;
		}
	}

	for(my $i = 0 ; $i < $cCBM ; $i++) {
		my $ikECBM = $ikECBM[$i];
		if($ikECBM+1 == $ikECBM[$i+1] and $pDA->[$iECBM][$ikECBM] > $pDA->[$iECBM][$ikECBM+1]) {
			next;
		}
		elsif($ikECBM-1 == $ikECBM[$i-1] and $pDA->[$iECBM][$ikECBM] > $pDA->[$iECBM][$ikECBM-1]) {
			next;
		}

		my $i1;
		if($pDA->[2][$ikECBM+1] ne '') {
			for(my $ik = $ikECBM+1 ; $ik < $nData ; $ik++) {
				last if($pDA->[2][$ik] eq '');
				$i1 = $ik;
			}
		}
		else {
			for(my $ik = $ikECBM-1 ; $ik >= 0 ; $ik--) {
				last if($pDA->[2][$ik] eq '');
				$i1 = $ik;
			}
		}
		my ($kx0, $ky0, $kz0) = ($pDA->[0][$ikECBM], $pDA->[1][$ikECBM], $pDA->[2][$ikECBM]);
		my ($kx1, $ky1, $kz1) = ($pDA->[0][$i1],     $pDA->[1][$i1],     $pDA->[2][$i1]);
		for(my $iE = $iECBM ; $iE < $nDataRow ; $iE++) {
			last if($pLabelArray->[$iE] !~ /ECBM/i);
			next if($ECBM+$torE < $pDA->[$iE][$ikECBM]);

			my $E  = $pDA->[$iE][$ikECBM];
			my $me = $pDA->[$ime+($iE-$iECBM)][$ikECBM];
printf "CBM: ik=%03d k=($kx0,$ky0,$kz0)->($kx1,$ky1,$kz1) ECBM=$ECBM eV  me=$me\n", $ikECBM;
	
			$CBInf[$cCB] = {
				ik   => $ikECBM,
				k    => "$kx0 $ky0 $kz0",
				kdir => "$kx1 $ky1 $kz1",
				E    => $ECBM,
				me   => $me,
				};
			$cCB++;
		}
	}

print "\n";
	$inf{pVBInf} = \@VBInf;
	$inf{pCBInf} = \@CBInf;

	return \%inf;
}
