#!perl

#
#  This file is common to a number of the files in the TightKnot directory. It includes utility functions for parsing filenames, generating TeX, and so forth.
#

use Getopt::Long;

sub parsefilename {

  my $filename = @_[0];
  my @fnparts;

  my @summands;
  my @sumtags;

  my $totalcr = 0;
  my $totalcomp = 1;

  my $cr;
  my $comp;
  my $ind;

  my $tag = "";

  $filename =~ s/\.vect//g;
  $filename =~ s/\.\/vects\/kl\_//g;

#  print "filename: $filename \n";

  @fnparts = split(/\_/,$filename);

  print "fnparts: @fnparts \n";

  my $i;
  my @summand_texkeys;
  my $treeTag;

  for ($i=0;$i<=$#fnparts;$i++) { 

   print "Now checking $fnparts[$i] $fnparts[$i+1] ... \n";

    if ($fnparts[$i] =~ /^\d+$/ && $fnparts[$i+1] =~ /^\d+$/) {

      if ($fnparts[$i+2] =~ /^\d+$/ || $fnparts[$i+2] =~ /^(r|m)$/) {  # We have a link or an (m/r) tag

	if ($fnparts[$i+2] =~ /^\d+$/) {

	  $cr = $fnparts[$i]; $comp = $fnparts[$i+1]; $ind = $fnparts[$i+2];
	  $totalcr += $cr; $totalcomp += $comp - 1;
	  push (@summand_texkeys,"$cr^{$comp}_{$ind}");

	  print "so far, texkeys = @summand_texkeys\n";

	} else {

	  $cr = $fnparts[$i]; $comp = 1; $ind = $fnparts[$i+1];
	  $totalcr += $cr; $totalcomp += $comp - 1;

	  # We have an r/m tag, which should appear in the tex key 

	  push (@summand_texkeys,$cr."_{$ind}".$fnparts[$i+2]);

	  print "r/m tag: $cr  $ind  $fnparts[$i+2] texkeys = @summand_texkeys\n";

	}

	print "\tpushing ".$fnparts[$i]."_".$fnparts[$i+1]."_".$fnparts[$i+2]."\n";

	push(@summands,$fnparts[$i]."_".$fnparts[$i+1]."_".$fnparts[$i+2]);
	$i += 2; # skip to the next part

      } else {

	$cr = $fnparts[$i]; $comp = 1; $ind = $fnparts[$i+1];
	$totalcr += $cr; $totalcomp += $comp - 1;

	push (@summand_texkeys,$cr."_{$ind}");
	print "\tpushing ".$fnparts[$i]."_".$fnparts[$i+1]."\n";

	push(@summands,$fnparts[$i]."_".$fnparts[$i+1]); # A standard link
	$i += 1; # skip ahead by 2 fragments

      }

      if ($totalcomp > 1 && $#summands > 0) { # Composite link.

	  if ($i == $#fnparts-2) { # we have a treetag

	      $treeTag = $fnparts[$i+1];
	      $tag = $fnparts[$i+2];
	      $i += 2;
	      
	  } elsif ($i == $#fnparts-1) { # no treetag
	      
	      $tag = $fnparts[$i+1];
	      $i++;

	  }
	  
	  } elsif ($i == $#fnparts-1) { # We have a tag, and we're not a composite link

	      $tag = $fnparts[$i+1];
	      $i++;
       
	  }

    }
   
  }

  print "summands: @summands \n";
  
  my $knottype = join("_#_",@summands);
  
  if (defined $treeTag) {

      $knottype = $knottype."_$treeTag";

  }

  my %retstuff;

  @{$retstuff{summands}} = @summands;
  $retstuff{tag} = $tag;
  $retstuff{knottype} = $knottype;

  $retstuff{cr} = $totalcr;
  $retstuff{comp} = $totalcomp;
  
  if (scalar @summands > 1) { $retstuff{index} = 1; }
  else { $retstuff{index} = $ind; }

  $retstuff{tex} = join(" \\# ",@summand_texkeys);

  return %retstuff;

}

sub standardknottype {

  my $knottype = @_[0];
  my @parts;

  @parts = split(/\_/,$knottype);

  if (@parts[$#parts] =~ /^(r|m)/) {

    return $parts[0]."_".$parts[1];

  }

  return $knottype;

}

sub crossing_number { 
   
    my %knots = %{@_[0]};
    my $key = @_[1];
    my $cr;

    if (defined $knots{$key}{summands}) {

	$cr = 0;
	
	foreach ($knots{$key}{summands}) {

	    if ($_ =~ /^(\d+)_.+/) {

		$cr += $1;

	    } else {

		die("crossing_number: Couldn't parse summand $_ \n");

	    }

	}

    } else {

	if ($key =~ /(\d+)_.+/) {

	    $cr = $1;

	} else {

	    die("crossing_number: Couldn't parse $key. \n");

	}

    }

    return $cr;

}

sub prime_summands { 

    my %knots = %{@_[0]};
    my $key = @_[1];

    if (defined $knots{$key}{summands}) {

	return scalar @{$knots{$key}{summands}};

    } else {

	return 1;

    }

}

sub stored_writhe { 

  my %knots = %{@_[0]};
  my $knottype = @_[1];
  my $raw_writhe;

  $raw_writhe = $knots{standardknottype($knottype)}{writhe};

  if ($knottype =~ /m/) {

    $raw_writhe *= -1.0;

  } 

  return $raw_writhe;

}

sub compare_summands {
  
  my @A = @{@_[0]};
  my @B = @{@_[1]};
  
  my $i;

  if ((scalar @A <=> scalar @B) ne 0) { 
    
    #print "Different number of summands"; 
    return (scalar @A <=> scalar @B); 

  }

  foreach $i (0..(scalar @A - 1)) {
    
    my @aparts,@bparts;
    
    @aparts = split(/_/,$A[$i]);
    @bparts = split(/_/,$B[$i]);

    #print "aparts: @aparts\n";
    #print "bparts: @bparts\n";
    
    unless (defined($aparts[2])) {
      
      $aparts[2] = 'a';
      
    } 
    
    unless (defined($bparts[2])) {
      
      $bparts[2] = 'a';
      
    }
    
    my $j;

    #print "aparts: @aparts\n";
    #print "bparts: @bparts\n";
    
    foreach $j (0..1) {
      
      if (($aparts[$j] <=> $bparts[$j]) ne 0) {

	#print "j = $j  aparts[j] = $aparts[$j]  bparts[j] = $bparts[$j] \n";
	
	return $aparts[$j] <=> $bparts[$j];
	
      }
      
    } 

    if (($aparts[2] cmp $bparts[2]) ne 0) {return $aparts[2] cmp @bparts[2];}
    
  }
  
  return 0; # We ran out of summands
  
}


sub sorted_knot_types { 

    my %knots = %{@_[0]};
    my $composites = @_[1];
    my @keys; 

    foreach $_ ( keys ( %knots )) {

	unless ( $_ =~ /vect/) {

	    print "Considering $_, ps = ".prime_summands(\%knots,$_)."\n";

	    if ($composites =~ /composites/ || prime_summands(\%knots,$_) == 1) {

		push(@keys,$_);

	    }

	}

    }

    print "Sorting ".scalar @keys." knot types...\n";
    
    my @sortkeys = sort{ 
	    
	if (($knots{$a}{cr} <=> $knots{$b}{cr}) eq 0 ) {
	    
	    if ((prime_summands(\%knots,$a) <=> prime_summands(\%knots,$b)) eq 0) {
		
		if (($knots{$a}{comp} <=> $knots{$b}{comp}) eq 0 ) {
		    
		    if (prime_summands(\%knots,$a) == 1) {

			return $knots{$a}{index} <=> $knots{$b}{index};
		    
		    } else {

		      my $retval;

		      $retval = compare_summands($knots{$a}{summands},$knots{$b}{summands});

		      # Now we need to compare each summand, sorting in dictionary order
		      #print "$a, $b $retval\n";

		      return $retval; 

		    }
				
		}
		
		return $knots{$a}{comp} <=> $knots{$b}{comp};
		
	    }

	    return prime_summands(\%knots,$a) <=> prime_summands(\%knots,$b);

	}

	return $knots{$a}{cr} <=> $knots{$b}{cr};
	
    } @keys ;

    return @sortkeys;

}

my $configtag= '';
GetOptions ( 'tag=s' => \$configtag);

unless (defined $configtag) {

  print("usage: setupMangleRun -tag=xyz\n\n");
  print("       produces configurations called (knot)_xyzconfig01.vect ... (knot)_xyzconfig20.vect\n");

  die();

}

@vects = <*.vect>;

foreach $guy (@vects) {

  %fparse = parsefilename($guy);

  for $n (1..20) {

    $nf = sprintf("%03d",$n);    
    $newname = "kl_$fparse{knottype}_${configtag}config${nf}.vect";

    `splinevect -r 2 -o $newname $guy`;
    print("$guy -> $newname\n");

  }
  
  `rm $guy`;

}
