use strict;
use warnings;

use application "polytope";

foreach my $file (split("\n", `find testfiles -name *.fail`)){
   print "Repairing $file: ";
   repair_splitter($file);
}

sub repair_splitter {
   my($file) = @_;
   if($file =~ m/should_fail/){ 
      print "Should fail anyway!\n";
      return; 
   }
   if($file =~ m/randomBFS/){
      print "Case not covered!\n";
      return; 
   }
   if($file =~ m/random_walk/){
      print "Case not covered!\n";
      return; 
   }
   if($file =~ m/estimates/){
      print "Case not covered!\n";
      return; 
   }
   return repair_fail($file);
}

sub repair_fail {
   my($fail) = @_;
   my($orig) = $fail =~ m/(.*)\.fail/;
   my @entire_fail = split("\n", `cat $fail`);
   my @entire_orig = split("\n", `cat $orig`);
   if(scalar @entire_orig == scalar @entire_fail){
      my $can_repair = 1;
      for(my $i=0; $i<scalar @entire_orig; $i++){
         if($entire_orig[$i] ne $entire_fail[$i]){
            $can_repair &= compare_lines($entire_orig[$i], $entire_fail[$i]);
         }
      }
      if($can_repair){
         `mv $fail $orig`;
         print "Can be repaired!\n";
      } else {
         print "Could not be repaired!\n";
      }
   } else {
      print "$orig is unrepairable!\n";
   }
}

sub compare_lines{
   my($orig, $fail) = @_;
   my($ostart, $otriang, $oend) = $orig =~ m/(.*)(\{\{.*\}\})(.*)/;
   my($fstart, $ftriang, $fend) = $fail =~ m/(.*)(\{\{.*\}\})(.*)/;
   my $check = $ostart eq $fstart;
   $check &= compare_triangs($otriang, $ftriang);
   if($orig !~ m/perm/){
      $check &= $oend eq $fend;
   } else {
      my($operm) = $oend =~ m/perm: (\[.*\])/;
      my($fperm) = $fend =~ m/perm: (\[.*\])/;
      $check &= compare_triangs_with_perm($otriang, $operm, $ftriang, $fperm);
   }
   return $check;
}

sub parse_triang{
   my $t = shift;
   $t =~ s/{/[/g;
   $t =~ s/}/]/g;
   return new Set<Set<Int>>(eval($t));
}

sub compare_triangs_with_perm {
   my($t0, $p0, $t1, $p1) = @_;
   $t0 = parse_triang($t0);
   $p0 = new Array<Int>(eval($p0));
   $t1 = parse_triang($t1);
   $p1 = new Array<Int>(eval($p1));
   my $target = group::action_inv<group::on_elements>($p0, $t0);
   $target = group::action<group::on_elements>($p1, $target);
   if($t1 != $target){
      die "Wrong order?\n";
   }
   return $t1 == $target;
}

sub compare_triangs{
   my($t0, $t1) = @_;
   # print "t0: $t0\n";
   $t0 = parse_triang($t0);
   $t1 = parse_triang($t1);
   return $t0 == $t1;
}
