###########################
#  Match::PosalCodes.pm   #
#      Version 1.02       #
#    (c) Ed Egan 2009     # 
###########################

package PostalCodes;
use strict;
use warnings;

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    $self->{ISO}=shift;
    my %ApprovedISOs=(
                    "AU"=>1,
                    "BE"=>1,
                    "CA"=>1,
                    "CH"=>1,
                    "DE"=>1,
                    "ES"=>1,
                    "FI"=>1,
                    "FR"=>1,
                    "GB"=>1,
                    "HU"=>1,
                    "IE"=>1
                   );
    $self->{APPROVED}=\%ApprovedISOs;
    if (defined ($self->{APPROVED}->{$self->{ISO}})) {$self->{APPROVED_OK}=1;}
    return $self;
}

sub ExtractPostalCode {
    my $self=shift;
    my $String=shift;
    my $OrigString=$String;
    my $PostCode=undef;
    if ($self->{APPROVED_OK}) {
        my $Method=$self->{ISO};
        ($PostCode,$String)=$self->$Method($String);
    }
    return ($PostCode,$String);
}        

sub Template {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        #$PostCode=~s/[^0-9]//g;
        #$PostCode=$self->FixLength($PostCode,4);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub AU {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='(NSW|Nsw|ACT|Act|VIC|Vic|QLD|Qld|SA|Sa|WA|Wa|TAS|Tas|NT|Nt|Au|AU)?(\w\.\w\.\w\.)?\.?\s?-?\s?\d{4,4}';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        my $Territory=undef;
        $PostCode=~/(NSW|Nsw|ACT|Act|VIC|Vic|QLD|Qld|SA|Sa|WA|Wa|TAS|Tas|NT|Nt)/;
        $Territory=$1;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,4);
        if ($Territory) {
            $Territory=uc($Territory);
            $PostCode=$Territory."-".$PostCode;
        }
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub BE {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='\d{0,3},?\s?-{0,2}\s?B?[EF]?\.?\s?-{0,2}\s?\d{1,5}-?';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,4);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub CA {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='[A-Z0-0][0-9O-O][A-Z0-0]\s?\-?\s?([0-9O-O][A-Z0-0][0-9O-O])? ';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/-/ /g;
        $PostCode=~s/\s{1,}/ /g;
        $PostCode=~s/^0/O/;
        $PostCode=~s/^([A-Z])O/$10/;
        $PostCode=~s/^([A-Z]\d)0/$1O/;
        $PostCode=~s/^([A-Z]\d[A-Z] )O/$10/;
        $PostCode=~s/^([A-Z]\d[A-Z] \d)0/$1O/;
        $PostCode=~s/^([A-Z]\d[A-Z] \d[A-Z])O/$10/;
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub CH {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='(CH|Ch|)\s?-?\s?\d{3,4}-?';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,4);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub DE {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='\(?(DE|D|1|W|O|0)\.?-?[O0]?(BRD|1|)\s?-?\s?\d{2,5}\)?';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        my $Prefix=undef;
        $PostCode=~/((DE|D|1|W|O|0)\.?-?[O0]?(BRD|1|))/;
        $Prefix=$1;
        $Prefix=~s/\W//g;
        $Prefix=~s/0/O/g;
        if (!($Prefix eq "0" || $Prefix eq "W")) {$Prefix="";}
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,5);
        if ($Prefix) {$PostCode=$Prefix."-".$PostCode;}
        $String=~s/[0-9]//g;
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub ES {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='(E|ES|)\d{0,2},?\s?-{0,2}\s?\d{2,5}-?(IBI|)';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        if ($PostCode=~/(\d{4,5})/) {$PostCode=$1;}
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,5);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub FI {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='(FI|FIN|Finn|FINN|FIB|SF)?\s?-?-?\s?\d{4,7}';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,5);
        $PostCode=$self->FixLength($PostCode,4);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub FR {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='\(?F?R?\.?\s?\d?-?\s?\d{2,3}\.?\s?\/?\d{0,3}-?\)?';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,5);
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub GB {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='[A-Z]{1,2}[0-9]{1,2}[A-Z]{0,1}\s[0-9][A-Z]{2,2}';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
    }
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub HU {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='(H|HU)?\s?-?\s?\d{2,4}-?\d{0,2}';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
        $PostCode=~s/[^0-9]//g;
        $PostCode=$self->FixLength($PostCode,4);
    }
    $String=~s/(^| |-|,)(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX)( |,|-|$)/ /;
    $String=~s/(^| |-|,)u\.?\s?\d{1,3}\/?\w?( |,|-|$)/ /i;
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}


sub IE {
    my $self=shift;
    my $String=shift;
    my $PostCode=undef;
    my $RegEx='\d{1,2}';
    if ($String=~/(^| |-|,)$RegEx( |,|-|$)/) {
        $String=~s/(^| |-|,)($RegEx)( |,|-|$)/ /;
        $PostCode=$2;
    }
    $String=~s/(^| |-|,)Co\.( |,|-|$)/ County /;
    $String=~s/^\s{1,}//; $String=~s/\s{1,}$//; $String=~s/,\s{0,},/,/; $String=~s/,$//; $String=~s/\s{1,}$//; $String=~s/\s{1,}/ /;
    return ($PostCode,$String);    
}

sub FixLength {
    my $self=shift;
    my $Code=shift;
    my $Length=shift;
    until (length($Code) >= $Length) {$Code=$Code."0";}
    until (length($Code) <= $Length) {$Code=chop($Code);}
    return $Code;
}

1;
