#!/bin/perl

#
# This program searches the KnotDB database for files, then checks that they are of the right knottype.
#

use strict;
use warnings;
use File::Slurp;
use File::Copy;
use File::Path;
use Data::Dumper;

sub knotok {

  my $filename = $_[0];

  open KNOTTYPE, "knottype -vq ./vects/$filename |";
  my $result;

  while (<KNOTTYPE>) {

    if (m/RESULT: (.+)/) {

      if ($1 =~ m/Maybe ok/ || $1 =~ m/Ok/) {

	return (1 == 1);
	
      }

    }

  }

  return (0 == 1);

}

sub knottype {

  my $filename = $_[0];

  open KNOTTYPE, "knottype -kq ./vects/$filename |";
  my %types = ( );

  while (<KNOTTYPE>) {

    if (m/\|\<(\d+)_(\d+) \(.+?\)\>\|/) { # This line is a knot type. 

      $types{"$1_$2"} = "possible";

    }

  }

  # We now have a hash of possible knottypes.

  return keys %types;

}    

# We start by loading the database.

my $DBFILE = read_file('KnotDB.pl');
my %knots;
eval($DBFILE);

my %wknots = %knots;
my $numkeys = keys ( %wknots );

print "We have $numkeys entries in the original database.\n";

chdir("./vects");
my @vects;
@vects = <*.vect>;
chdir("..");

print "We have ".scalar @vects." files in ./vects/...";

foreach (@vects) {

  unless (defined $knots{$_}) {

    print "$_ is in ./vects but has no entry in KnotDB.pl\n";
    die;

  }

}

print "all of which have entries in KnotDB.pl\n";

print "Checking knottypes...\n";

my $key;
my @goodguys;
my @badguys;
my @lostboys;

my $knots;
$knots = 0;

#if (-d "./proposedvects/") { `rm -fr proposedvects`; }
#mkdir ("./propoprsedvects/") or die("Couldn't make ./proposedvects");

foreach $key ( sort(keys %wknots) ) {

  if ($key =~ m/vect/) {

    unless (defined $knots{$key}{knot_type}) {
      
      print "File $key has no knot type!\n";
      die();
      
    }
    
  }
  
  if ($key =~ /.vect/ && $knots{$key}{knot_type} =~ m/(\d+?)_(\d+?)/ ) {
    
    $knots++;
    
    print "File $key ";
    
    if ($key =~ m/open/ || knotok($key)) {
      
      print "is ok...\n";
      push @goodguys, $key;
      #copy("./vects/$key","./proposedvects/$key") or die("Couldn't copy $key to ./proposedvects");
      
    } else {
      
      my @types;
      @types = knottype($key);
      
      print "should have knot type in @types...";
      
      if (scalar @types == 1) {
	
	my $tag;
	my $newname;
	
	$key =~ m/kl_$wknots{$key}{knot_type}_(.+?)\.vect/;
	$newname = "kl_$types[0]_".$1."uf.vect";
	
	print "which is unique, so we can copy to $newname...";

	if (-f "./vects/$newname") {
	  $newname =~ s/uf\.vect/uff\.vect/;

	  if (-f "./vects/$newname/") {

	    print "name collision! ./vects/$newname already exists!\n";
	    die;

	  }

	}

	copy("./vects/$key","./vects/$newname") or die("Couldn't copy ./vects/$key to ./vects/$newname");
	push @badguys, $key;
	
      } else {
	
	print "which is not unique, so we can't save the file...";
	push @lostboys, $key;
	
      }
      
      print "and delete $key from wknots...";
      delete $knots{$key};
      
      print "and remove $key from the svn.\n";
      `svn rm ./vects/$key`;
      
    }      
    
  }
  
}

print "\n\nWe started with ".scalar @vects." files in ./vects/ \n";
print "We found $knots entries in the KnotDB database.\n";
print "We found ".scalar @goodguys." files where the knot type matches.\n";
print "We found ".scalar @badguys." files where the knot type doesn't match, but we could save the file.\n";
print "We found ".scalar @lostboys." files where the knot type doesn't match and we couldn't save the file.\n";

my $total;
$total = scalar @goodguys + scalar @badguys + scalar @lostboys;
my $newtotal;

$newtotal = scalar @goodguys + scalar @badguys; 

print "This totalled $total files processed and $newtotal files which should be in ./vects.\n\n";

my @proposedglob;
chdir("./vects");
@proposedglob = <*.vect>;
chdir("..");

print "We actually have ".scalar @proposedglob." files in ./vects.\n";

print "Writing ProposedKnotDB.pl. We have updated ./vects/ \n\n";

open(KNOTDB,'>ProposedKnotDB.pl') or die "Unable to create Knot database.";
print KNOTDB Data::Dumper->Dump([\%knots],['*knots']),"\n";
close KNOTDB;

