#!/usr/bin/perl

use strict;

use lib 'd:/Programs/Perl/lib';
use lib "$ENV{TkPerlDir}/lib";
use Deps;
use Utils;
use JFile;
use Crystal::VASP;

my $LatticeSystem = 'cubic';
#my $LatticeSystem = 'tetragonal';
my $Denominator   = 1000;

my $BaseFileName = ($ARGV[0])? $ARGV[0] : 'KPOINTS';

my $vasp = new VASP;

my $EIGENVALOriginal = $vasp->GetEIGENVALFileName($BaseFileName);
my $EIGENVALOutput   = Deps::ReplaceExtension($EIGENVALOriginal, ".band");
print "Input EIGENVAL:  $EIGENVALOriginal\n";
print "Output EIGENVAL: $EIGENVALOutput\n";

my ($pBandInf, $pBands) = &ReadEIGENVAL($EIGENVALOriginal);
my $nK = @$pBands;
print "nK=$nK\n";
my @BandArray;
for(my $i = 0 ; $i < $nK ; $i++) {
	my $pKInf = $pBands->[$i];
print "$i: pKInf: $pKInf\n";
	my $ikx = int($pKInf->{kx}*$Denominator+0.01);
	my $iky = int($pKInf->{ky}*$Denominator+0.01);
	my $ikz = int($pKInf->{kz}*$Denominator+0.01);
	&AddBandToArray(\@BandArray, $ikx, $iky, $ikz, $pKInf);
	if($LatticeSystem eq 'cubic') {
		&AddBandToArray(\@BandArray, $ikx, $ikz, $iky, $pKInf);
		&AddBandToArray(\@BandArray, $iky, $ikx, $ikz, $pKInf);
		&AddBandToArray(\@BandArray, $iky, $ikz, $ikx, $pKInf);
		&AddBandToArray(\@BandArray, $ikz, $ikx, $iky, $pKInf);
		&AddBandToArray(\@BandArray, $ikz, $iky, $ikx, $pKInf);
	}
	elsif($LatticeSystem eq 'tetragonal') {
		&AddBandToArray(\@BandArray, $iky, $ikx, $ikz, $pKInf);
	}
	else {
print "Lattice system [$LatticeSystem] is not supported\n";
	}
}

my $d = 10;
my @OutputKPoints = (
	[0,     0, 5/$d],
	[0,     0, 4/$d],
	[0,     0, 3/$d],
	[0,     0, 2/$d],
	[0,     0, 1/$d],
	[0,     0,   0],
	[1/$d,   0,   0],
	[2/$d,   0,   0],
	[3/$d,   0,   0],
	[4/$d,   0,   0],
	[5/$d,   0,   0],
	[5/$d, 1/$d,   0],
	[5/$d, 2/$d,   0],
	[5/$d, 3/$d,   0],
	[5/$d, 4/$d,   0],
	[5/$d, 5/$d,   0],
	[5/$d, 5/$d, 1/$d],
	[5/$d, 5/$d, 2/$d],
	[5/$d, 5/$d, 3/$d],
	[5/$d, 5/$d, 4/$d],
	[5/$d, 5/$d, 5/$d],
	[4/$d, 4/$d, 4/$d],
	[3/$d, 3/$d, 3/$d],
	[2/$d, 2/$d, 2/$d],
	[1/$d, 1/$d, 1/$d],
	[0,     0,   0],
	[1/$d, 1/$d,   0],
	[2/$d, 2/$d,   0],
	[3/$d, 3/$d,   0],
	[4/$d, 4/$d,   0],
	[5/$d, 5/$d,   0],
	);

my $out = new JFile($EIGENVALOutput, "w") or die "$!: Can not write to [$EIGENVALOutput]\n";
my $pHeader = $pBandInf->{pHeader};
for(my $i = 0 ; $i < @$pHeader ; $i++) {
	$out->print($pHeader->[$i]);
}
print "na, nk, nlevels: $pBandInf->{na}, ", scalar @OutputKPoints, ", $pBandInf->{nLevels}\n";
$out->printf("%5d %4d %4d\n", $pBandInf->{na}, scalar @OutputKPoints, $pBandInf->{nLevels});

for(my $i = 0 ; $i < @OutputKPoints ; $i++) {
	my $ikx = int($OutputKPoints[$i][0]*$Denominator+0.01);
	my $iky = int($OutputKPoints[$i][1]*$Denominator+0.01);
	my $ikz = int($OutputKPoints[$i][2]*$Denominator+0.01);
	my $pKInf = $BandArray[$ikx][$iky][$ikz];
print "$i: $ikx, $iky, $ikz: $pKInf->{Header}";

	$out->printf($pKInf->{Blank});
	$out->printf($pKInf->{Header});
	my $pLevels = $pKInf->{pLevels};
	if(!defined $pLevels) {
		print "Can not find pLevels for $ikx,$iky,$ikz\n";
		exit;
	}
	for(my $il = 0 ; $il < @$pLevels ; $il++) {
		$out->printf($pLevels->[$il]);
	}
}
exit;

sub AddBandToArray
{
	my ($pBandArray, $ikx, $iky, $ikz, $pKInf) = @_;

	$pBandArray->[$ikx][$iky][$ikz] = $pKInf;
print "ik: $ikx, $iky, $ikz\n";
}

sub ReadEIGENVAL
{
	my ($fname) = @_;

	my $in = new JFile($fname, "r") or die "$!: Can not read [$fname]\n";
	my @header;
	for(my $i = 0 ; $i < 5 ; $i++) {
		$header[$i] = $in->ReadLine();
	}
	my ($na, $nk, $nlevels) = Utils::Split("\\s+", $in->ReadLine());
print "na, nk, nlevels: $na, $nk, $nlevels\n";

	my %BandInf = (
		pHeader => \@header,
		na      => $na,
		nk      => $nk,
		nLevels => $nlevels,
		);

	my @Bands;
	my $c = 0;
	for(my $ik = 0 ; $ik < $nk ; $ik++) {
		my $blank  = $in->ReadLine();
		my $header = $in->ReadLine();
		my ($kx, $ky, $kz, $w) = Utils::Split("\\s+", $header);
		my @levels;
		for(my $il = 0 ; $il < $nlevels ; $il++) {
			$levels[$il] = $in->ReadLine();
		}
		my %KInf = (
			Blank  => $blank,
			Header => $header,
			kx     => $kx,
			ky     => $ky,
			kz     => $kz,
			w      => $w,
			pLevels => \@levels
			);
		$Bands[$c] = \%KInf;
		$c++;
	}
	$in->Close();
	
	$BandInf{pBands} = \@Bands;

	return (\%BandInf, \@Bands);
}
