use strict;
use warnings;

use Cwd;
use List::Util qw(min);

my $threshold=0.4;				#閾値
my $filename;
my @person;
my @dividename;
my $namemailline;
my $firstname;
my $lastname;
my $fullname;
my $firstlevenshtein;
my $lastlevenshtein;
my $fulllevenshtein;
my @mail;
my @name;
my @namemaillevenshtein;
my $similar1;
my $similar2;
my $similar3;
my @namemailline;
my @mailline;
my $mailname;
my $average;
my $maillevenshtein;
my $mail;
my @levenshteindata;
my @similar;
my $similarmax=0;
my $remChar = ">|<|\|";


my $i=0;
my $j;
my $k;
my $x=1;

my $str1;
my $str2;

&pickupname();
&examine();


#--------------------------------------------------------------------------------

#順番に比較対象を
sub pickupname {
	$filename=$ARGV[0];
	open FILE,"$filename";
	while($_=<FILE>){
		if($_ !~ /^0/){
			@person = split(/\t/,$_);
#person[0]=<名前>		person[1]=<アドレス>	
print "$person[0]";
				$firstname = "";
				$lastname = "";
				$fullname = "";
			
			@dividename = split(/ /,$person[0]);
			if(@dividename == 1){#１wordだったとき
				if($person[0]=~ /[a-zA-Z0-9\.\-\_\$]+\@[a-zA-Z0-9\.\-\_]+/){#アドレスだった時
					@namemailline = split(/@/,$person[0]);	#＠の前後で分けた
					$fullname = $namemailline[0];
					#print "$fullname\n";
				}
				else{#アドレス以外の１wordだったとき
					$fullname = $person[0];
					#print "$fullname\n";
				}
			}
			elsif(@dividename == 2){#２wordだったとき
				$firstname = $dividename[0];
				$lastname = $dividename[1];
				$fullname = $person[0];
				#print "$fullname\n";
			}
			elsif(@dividename == 3){   #Jess M. Holleなどのミドルネームがある人対象だが、aaa bbb cccみたいなやつもひっかかる
				$firstname = $dividename[0];
				$lastname = $dividename[2];
				$fullname = $person[0];
				#print "$fullname\n";
			}
			else{#４word以上の人
				$fullname = $person[0];
				#print "$fullname\n";
 			}
			
			@mailline = split(/@/,$person[1]);	#＠の前後で分けた
			$mailname = $mailline[0];
			
#################################################
#名前にいろいろある・・・
#Sander Holthaus Orange XL
#Jess M. Holle
#ranier
#pradeep kumar
#rbowen@rcbowen.com#など。。。以下名前をfirstname,lastname,fullnameに分けられたとして考える 
#################################################

			$firstname =~ s/$remChar//g;
			$name[$i][0] = $firstname;

			$lastname =~ s/$remChar//g;
			$name[$i][1] = $lastname;

			$fullname =~ s/$remChar| //g;
			$name[$i][2] = $fullname;

			$mailname =~ s/$remChar//g;
			$mail[$i] = $mailname;

                        for (my $k = 0; $k <= 2; $k++) {
                            if($name[$i][$k] eq ''){
				$name[$i][$k] = ' ';#############################################################
                            }
                        }
			if($mail[$i] eq ''){
				$mail[$i] = ' ';#############################################################
			}

			$name[$i][3] = $person[1];

			$i++;
			
		}
		
	}
	close (FILE);
}

sub examine{
	open(SimFILE, ">>Similarity.txt") or die "cannot open savefile.\n";
	for($j=0; $j<($i-1); $j++){
#		for($k=$j+1; $k<=($i-1); $k++){
		for($k=$j+1; $k<=($i-1); $k++){

			#名前同士チェック
#			$firstlevenshtein = levenshtein($name[$j][0], $name[$k][0]);	#firstname同士で比較
#			$lastlevenshtein = levenshtein($name[$j][1], $name[$k][1]);	#lastname同士で比較
#			$fulllevenshtein = levenshtein($name[$j][2], $name[$k][2]);	#fullname同士で比較


			($firstlevenshtein, $lastlevenshtein, $fulllevenshtein, $maillevenshtein, $namemaillevenshtein[0], $namemaillevenshtein[1], $namemaillevenshtein[2])
                            = levenshtein($name[$j][0], $name[$k][0],
                                          $name[$j][1], $name[$k][1],
                                          $name[$j][2], $name[$k][2],
                                          $mail[$j], $mail[$k],
                                          $mail[$j], $name[$k][0],
                                          $mail[$j], $name[$k][1],
                                          $mail[$j], $name[$k][2]);

                        if ($name[$j][0] eq ' ' and $name[$k][0] eq ' ') {
                            $firstlevenshtein = 0;
                        }
                        if ($name[$j][1] eq ' ' and $name[$k][1] eq ' ') {
                            $lastlevenshtein = 0;
                        }
                        if ($name[$j][2] eq ' ' and $name[$k][2] eq ' ') {
                            $fulllevenshtein = 0;
                        }


                     
                            $average = ($firstlevenshtein + $lastlevenshtein)/2;
                            my $max = min($average, $fulllevenshtein, $maillevenshtein, $namemaillevenshtein[0], $namemaillevenshtein[1], $namemaillevenshtein[2]);
                               print SimFILE join(' ',"$name[$j][3]	$name[$k][3]	$max	\n");
                            
                            
                        
		}
	}
	close(SimFILE);
}

sub levenshtein
{
    my @args = @_;
    my @result = ();

    for (my $i = 0; $i <= $#args; $i+=2) {
        my $s1 = $args[$i];
        my $s2 = $args[$i+1];

        my ($len1, $len2) = (length $s1, length $s2);

        if ($len1 == 0) {
            push(@result, $len2);
            next;
        }
        if ($len2 == 0) {
            push(@result, $len1) ;
            next;
        }

        my %mat;
        
        for (my $i = 0; $i <= $len1; ++$i){
            for (my $j = 0; $j <= $len2; ++$j){
                $mat{$i}{$j} = 0;
                $mat{0}{$j} = $j;
            }
            $mat{$i}{0} = $i;
        }
        
        my @ar1 = split(//, $s1);
        my @ar2 = split(//, $s2);
        
        for (my $i = 1; $i <= $len1; ++$i) {
            for (my $j = 1; $j <= $len2; ++$j) {
                my $cost = ($ar1[$i-1] eq $ar2[$j-1]) ? 0 : 1;
                $mat{$i}{$j} = minLev([$mat{$i-1}{$j} + 1,
                                    $mat{$i}{$j-1} + 1,
                                    $mat{$i-1}{$j-1} + $cost]);
            }
        }
        push(@result, $mat{$len1}{$len2});
    }
    return @result;
}
sub minLev
{
    my @list = @{$_[0]};
    my $min = $list[0];
    foreach my $i (@list) {
        $min = $i if ($i < $min);
    }
    return $min;
}

