#!/usr/bin/perl

use strict;
use Getopt::Long qw(:config no_ignore_case);
use Data::Dumper;

use vars qw($index $tar $directories $tests $clean $all $directory $convert $initFile $help $force);


my %options=('i' => \$index,
	     'h' => \$help,
	     'C' => \$convert,
	     't' => \$tar,
	     'd' => \$directories,
	     'I' => \$initFile,
	     'T' => \$tests,
	     'c' => \$clean,
	     'a' => \$all,
	     'f' => \$force,
	     'D' => \$directory);

print "\n";
GetOptions(\%options,qw(I=s i=s C=s c=s m=s d=s t=s T=s a=s D=s f! h!));

if ($help){
    print "
Usage: weyl.pl -D inputDirectory [-kCtdTcah] [-I initFile]

Options:

h: print this file
C: convert from maple to magma
t: tar up a directory
d: make directories
I: initFile: magma init file
T: make magma test file
c: clean
a: all
f: force (no confirms)
D: source directory (required)
";
    exit;
}
unless ($directory){
    print "
You must specify a directory with -D option.
";
    exit;
}

my $modelsDir=$directory||die("Need to enter a directory with -D option");
#print "DIR:$modelsDir";
&makeIndex($index) if ($index);
#&mathematica($mathematica) if ($mathematica);
&tar($tar) if ($tar);
&makeDirectories($directories) if ($directories);
&makeTests($tests) if ($tests);
&clean($clean) if ($clean);
&convert($convert) if ($convert);
&all($all) if ($all);
    
sub makeIndex{
    my $type=$index;
    my @files;
    my $dir=$modelsDir.'/'.$type.'/packages';

    opendir DIR, $dir||die("Can't open $dir");
    @files= grep /^[0-9ZQ]+$/,readdir DIR;
    closedir DIR;
    
#    print "files:", join "\n", @files;
    my @z:=grep /Z/, @files;
    foreach  my $i (0..$#z){$z[$i] =~ s/Z//;}
    @z=sort {$a <=> $b} @z;
    
    my @q:=grep /Q/, @files;
    foreach  my $i (0..$#q){$q[$i] =~ s/Q//;}
    @q=sort {$a <=> $b} @q;

    open(OUT,">$dir/index")||die("Can't open $dir/index");

    print OUT "
intrinsic myCompletedZ()->SeqEnum
{}
return [";
print OUT  join ',', @z;
print OUT  "];
end intrinsic;

intrinsic myCompletedQ()->SeqEnum
{}
return [";
print OUT  join ',', @q;
print OUT  "];
end intrinsic;";
close(OUT);
}

sub makeDirectories{
    my $type=$directories||shift;
    print "Making directories for $type\n";
    unless (-e $modelsDir){
	print "The directory $modelsDir does not exist. Please create it.\n";
	exit;
    }
#    my @directories=($type,"$type/magma","$type/magma/trash","$type/magma/tests","$type/magma/packages","$type/magma/packages/tests","$type/mathematica");
    my @directories=($type,"$type","$type/trash","$type/tests","$type/packages","$type/packages/tests");
    foreach my $dir (@directories){
	my $d="$modelsDir/$dir";
	if (-e $d){
	    print "Don't need to make $d\n";
	}else{
	    print "Making $d\n";
	    mkdir $d||die("no:$d");
	}
    }
}
	
sub clean{
    my $type=$clean;
    print "\nCleaning up files in $modelsDir/$type\n";
    &confirm;
    unless (-e "$modelsDir/$type/trash"){
	print "Creating trash directory\n";
	`mkdir "$modelsDir/$type/trash"`;
    }

#    foreach my $d ("$modelsDir/$type/magma","$modelsDir/$type/raw","$modelsDir/$type/mathematica"){
    foreach my $d ("$modelsDir/$type"){
	print "Working on directory $d";
	opendir DIR, $d;
	my @files= grep /^[0-9ZQCpt]+$/,readdir DIR;
	closedir DIR;
	
	my @z:=grep /Z[0-9]*$/, @files;
	@z=sort {$a <=> $b} @z;
	
	my @zCpt:=grep /Z.*Cpt/, @files;
	@zCpt=sort {$a <=> $b} @zCpt;
	
	my @q:=grep /Q[0-9]*$/, @files;
	@q=sort {$a <=> $b} @q;    
	
	my @qCpt:=grep /Q.*Cpt/, @files;
	@qCpt=sort {$a <=> $b} @qCpt;
	
	print "\nWorking on integral files:", join ',', @z;
	print "\n rational files:", join ',', @q;
	print "\ncompact integral files:", join ',', @zCpt;
	print "\ncompact rational files:", join ',', @qCpt;
	print "\n";
	
	foreach my $file (@z){
	    print "\nWorking on $file\n";
	    my $number = $file;
	    $number =~ s/Z//;
	    if (-e "$d/Q$number"){
		`mv "$d/Q$number" "$d/trash"`;
		print "Removed $d/Q$number\n";
	    }
	    if (-e "$d/Q$number"."Cpt"){
		my $file="$d/Q$number"."Cpt";
		`mv $file "$d/trash"`;
		print "Removed $file\n";
	    }
	    
	    if (-e "$d/$file"."Cpt"){
		print "Remove larger of $file,$file"."Cpt    ";
		my @stats=stat "$d/$file";
		my $size=$stats[7];
		@stats=stat "$d/$file"."Cpt";
		my $sizeCpt:=$stats[7];
		print "$file:",$size," $file"."Cpt:",$sizeCpt,"\n";
		if ($size <$sizeCpt){
		    my $fileCpt="$d/$file"."Cpt";
		    print "Remove $fileCpt\n";
		    `mv $fileCpt $d/trash`;
		}
		if ($sizeCpt <$size){
		    print "Remove B $d/$file\n";
		    `mv $d/$file $d/trash`;
		}	    
	    }else{
		print "No compact file to check";
	    }
	}
	print "\n\nNow work on any remaining rational files\n";

	foreach my $file (@q){
	    if (-e "$d/$file"){
		print "\nWorking on $file\n";
		my $number = $file;
		$number =~ s/Q//;
		
		if (-e "$d/$file"."Cpt"){
		    print "Remove larger of $file,$file"."Cpt    ";
		    my @stats=stat "$d/$file";
		    my $siqe=$stats[7];
		    @stats=stat "$d/$file"."Cpt";
		    my $siqeCpt:=$stats[7];
		    print "$file:",$siqe," $file"."Cpt:",$siqeCpt,"\n";
		    if ($siqe <$siqeCpt){
			print "TEST:$siqe:$siqeCpt\n";
			my $fileCpt="$d/$file"."Cpt";
			print "Remove  C $fileCpt\n";
			`mv $fileCpt   $d/trash`;
		    }
		    if ($siqeCpt <$siqe){
			print "Remove  D $file\n";
			`mv $d/$file $d/trash`;
		    }	    
		}else{
		    print "No compact file to check";
		}
	    }
	}
	print "\nDone\n";
    }
}

sub tar{
    my $type=$tar;
    my $dir="$modelsDir/$type";    
    print "Tarring up directory:", $dir;
    my $tarFile="$dir/$type.tar";
    `tar cvf $tarFile --exclude trash --exclude packages --exclude tests --exclude \*.tar $dir`;
}

#  sub mathematica{
#      my $type=$mathematica;
#      my $inDir="$modelsDir/$type/magma";
#      my $outDir="$modelsDir/$type/mathematica";
#      opendir DIR, $inDir;
#      my @files= grep /^[0-9ZQCpt]+$/,readdir DIR;
#      closedir DIR;
#      foreach my $file (@files){
#  	print "Converting $file to mathematica\n";
#  	open(IN,"<$inDir/$file");
#  	open(OUT,">$outDir/$file");
#  	my $brackets=0;
#  	foreach my $line (<IN>){
#  	    $line =~ s/magma/mathematica/;
#  	    $line =~ s://(.*):(*$1*):;
#  	    $line =~ s/Integers\(\)/"Integers"/;
#  	    $line =~ s/Rationals\(\)/"Rationals"/;
#  	    $brackets=1 if ($line =~ /\[/);
#  	    $line =~ s/\[/\{/g;
#  	    $line =~ s/\]/\}/g;
#  	    if ($brackets){
#  		$line =~ s/:=/:=\{/;
#  		$line =~ s/;/\};/;
#  	    }
#  	    print OUT $line;				   
#  	}
#      }
#      close(IN);
#      close(OUT);
#  }

#make a file which can be loaded into magma to test all Magma files (not packages)

sub makeTests{
    my $type=$tests;
    print "Making magma test file magmaTest$type\n";
    my $inDir="$modelsDir/$type";
    my $outFile="magmaTest$type";
    opendir DIR, $inDir;
    my @files= grep /^[0-9ZQCpt]+$/,readdir DIR;
    closedir DIR;
    open(OUT,">$outFile");
    print OUT "load \"$modelsDir/$type/initData\";\n";
    print OUT "failed:=[];\npassed:=[];";
    foreach my $file (@files){
	my $logFile="$modelsDir/$type/tests/$file";
	print OUT "load \"$modelsDir/$type/$file\";\n";
	print OUT "x:=testMagmaFile(d,operators,F,dimension,format,\"$logFile\",\"$modelsDir\");\n";
	print OUT "
if (x eq 1) then Append(~passed,\"$file\");
else Append(~failed,\"$file\");
end if;
";
    }
    print OUT 
"
print \"Passed:\",passed;
print \"Failed:\", failed;
";
    close(OUT);
}

sub all{
    my $type=$all;
    print "Going to do everything for type $type\n";
    &makeDirectories($type);
    print "Done making directories for $type\n";
    open(OUT,">doAll$type")||die("no");
    print OUT <<END;
load init;
d:=init("$type");
command:="/home/jda/magma/weyl.pl -T $type";
System(command);
save "~/models/$type/init";
SetOutputFile("~/models/$type/CharacterTable": Overwrite:=true);
print d`T;
UnsetOutputFile();
SetOutputFile("~/models/$type/ConjugacyClasses": Overwrite:=true);
print d`C;
UnsetOutputFile();
load w;
doAll(d,1);
perlCommand(\"$type\",\"c\");
perlCommand(\"$type\",\"m\");
perlCommand(\"$type\",\"T\");
load magmaTest$type;
perlCommand(\"$type\",\"t\");
report(d);
exit;
END
    close(OUT);
    print "Done making magma load file doAll$type\n";
    print "Going to launch magma and run doAll$type\n";
    `magma -s doAll$type`;
    print "Done\n";
}

#convert maple to magma
#$convert is the source dir (with maple file)
#$directory is the target dir (magma)
#target directories will be created if don't exist
#use -I initFile if it is not in the target directory
#convert.pl -I initFile -D targetDirectory(magma) -c sourceDirectory(maple) type
sub convert{
    my $sourceDir=shift;
    my $targetDir=$directory;
    my $type=$ARGV[0];
    unless ($type){
	die("You must enter a type as final argument");
	}
    print "Creating file convertMapleMagma$type\n";

    my $out="convertMapleMagma$type";
    $initFile||"$targetDir/$type/initData";
    unless (-e $initFile){
	print("
Can't fine the initData file $initFile.
Looks in $targetDir/$type/initData by default.
Use -I initDataFile to specify a different one");
	exit;
    }

    open(OUT,">$out");
    print OUT "
load \"$initFile\";
perlCommand(\"$type\",\"$targetDir\",\"d\");
perlCommand(\"$type\",\"$targetDir\",\"i\");
saveData(d,\"$targetDir\");
";

    print "type:$type";
    print "dir: $sourceDir/$type";
opendir(DIR,"$sourceDir/$type")||die("Can't open $sourceDir/$type");
my @files = grep {/^[XQ].*/} readdir(DIR);
closedir DIR;

print "files:",@files;
    print "HERE";
foreach my $file (@files){
    print "Doing $file\n";
    my $number=$file;
    $number =~ s/[^0-9]//g;
    print OUT "
load \"$sourceDir/$type/$file\";
convertModuleMaple(d,ma,$number,\"$targetDir\");
";
}

close(OUT);
    print "
Done creating file $out
You can load this file in magma.
Do: load $out\n";
}

sub confirm{
    return if $force;
    print "Confirm [yes/no]: ";
    my $confirm=<STDIN>;
    chomp($confirm);
    unless ($confirm eq 'yes'){
	print "Aborted\n";
	exit;
    }
}
