# sql::site::inc_dexhits;

our @LocPercents = (
    # red/blue/yellow
    { walking => { chance => [qw/25 15 15 10 10 10 5 5 4 1/], category => undef } },

    # gold/silver/crystal
    undef,

    # ruby/sapphire
    { walking => { chance => [qw/20 20 10 10 10 10 5 5 4 4 1 1/], category => undef },
      surfing => { chance => [qw/60 30 5 4 1/], category => undef },
      fishing => { chance => [qw/70 30 60 20 20 40 40 15 4 1/], category => [qw/old old good good good super super super super super/] } },
);

our %LocModes = (
    'walking' => 'normal',
    'walking:grass' => 'grass',
    'walking:cave' => 'ground',
    'fishing' => 'ice',
    'fishing:old' => 'rock',
    'fishing:good' => 'steel',
    'fishing:super' => 'psychic',
    'surfing' => 'water',
);



# machines
our @TMs = map { [ undef,
    map { $_->moveid } Vee::DBI::Machine->search( moveid => { '!=' => undef }, generation => $_, { columns => 'moveid', order_by => '+id' } )
] } 0 .. $#Generations;
our %MoveTMs;
for my $gen (0 .. $#Generations) {
    for my $tm (1 .. $#{$TMs[$gen]}) {
        $MoveTMs{ $TMs[$gen][$tm] }[ $gen ] = $tm;
    }
}


our @AbilityNames = Vee::DBI::Ability->retrieve_column('name', { order_by => '+id' });

sub by_area ($$) {
    my ($a, $b) = @_;
    my $c = ('route' eq lc substr($a, 0, 5));
    my $d = ('route' eq lc substr($b, 0, 5));
    if ($c) { if ($d) { return substr($a, 6) <=> substr($b, 6); } else { return -1;                } }
    else    { if ($d) { return 1;                               } else { return lc($a) cmp lc($b); } }
}

# merge routine for the movelist
# I have no idea how this works
sub mergemoves {
    my @a = @{ $_[0] };
    my @b = @{ $_[1] };
    my ($pos, $epos, $tpos, $i, $j, $temppos, $w, @b2);

    $w = $#{ $a[ 0 ] };  # Columns of moves in the base array
    # Make room for the second array
    for $i (0 .. $#a) { $a[ $i ] = [ @{ $a[ $i ] }[0 .. ($w - 1)], 0, $a[$i][ -1 ] ] }
    $epos = $pos = 0;
    # Add the moves from the second list to the first list where they fit
    for $i (0 .. $#b) {
        while ($pos <= $#a and ($a[ $pos ][ -2 ] == 0 or $a[ $pos ][ -2 ] <= $b[ $i ][ -2 ])) { $pos++; }
        while ($pos > 0 and ($a[ $pos - 1 ][ -2 ] == 0 or $a[ $pos - 1 ][ -2 ] == $b[ $i ][ -2 ])) { $pos--; }

        $tpos = -1;
        for $temppos ($pos .. $#a) { if ($a[ $temppos ][ -1 ] == $b[ $i ][ -1 ]) { $tpos = $temppos; last; } }
        if ($tpos == -1 or (($tpos > $#a / 2) and ($i < $#b / 2))) { push @b2, $b[ $i ]; next; }
        $pos = $tpos; $a[ $pos ][ -2 ] = $b[ $i ][ 0 ];
    }
    @b = @b2; @b2 = ();

    # Add the rest!
    REST: for $i (0 .. $#b) {
        $pos = 0;
        while ($pos <= $#a and $a[ $pos ][ -2 ] <= $b[ $i ][ -2 ]) {
            if ($a[ $pos ][ -1 ] == $b[ $i ][ -1 ]) { push @b2, $b[ $i ]; next REST; }
            $pos++;
        }
        splice @a, $pos, 0, [ split(//, '0' x $w), $b[ $i ][ -2 ], $b[ $i ][ -1 ] ];
    }
    if (@b2) {
        @b = @b2;
        REST: for $i (0 .. $#b) {
            $pos = 0;
            while ($pos <= $#a) {
                if ($a[ $pos ][ -1 ] == $b[ $i ][ -1 ]) {
                    $temppos = 100; $tpos = $pos; while ($tpos <= $#a and ($temppos = $a[ $tpos ][ -2 ]) == 0) { $tpos++; }
                    if ($temppos >= $b[ $i ][ -2 ]) { $a[ $pos ][ -2 ] = $b[ $i ][ -2 ]; $b[$i] = ""; next REST; }
                } else {
                    if ($a[ $pos ][ -2 ] != 0 and $a[ $pos ][ -2 ] > $b[ $i ][ 0 ]) { splice @a, $pos, 0, [ split(//, '0' x $w), $b[ $i ][ 0 ], $b[ $i ][ 1 ] ]; $b[$i] = ""; next REST; }
                }
                $pos++;
            }
            splice @a, $pos, 0, [ split(//, '0' x $w), $b[ $i ][ 0 ], $b[ $i ][ 1 ] ]; $b[$i] = "";
        }
    }
    # Toss it back
    @{ $_[0] } = @a;
}

sub loc_equal {
    my ($a, $b) = @_;
    return &hashref_equal($a, $b);
}

# in: hash of mode => { category => { areas } }
sub loc_print {
    my ($loc, $icon, $color, $cols) = @_;
    return unless %$loc;
    my $rows = 1 + scalar keys %$loc;
    print qq'<tr style="background-color: #$color !important;"><th class="dex_locations_icon" colspan="3">$Icons{$icon}</th></tr>\n';
    for my $mode (sort by_area keys %$loc) {
        for my $cat (sort keys %{ $loc->{$mode} }) {
            print '<tr>';
            if ($cat eq 'default') { print qq'<td class="dex_locations_mode type-$LocModes{$mode}" colspan="2">$mode</td>'; }
            else { print qq'<td class="dex_locations_mode type-$LocModes{$mode}">$mode</td><td class="dex_locations_mode type-$LocModes{"$mode:$cat"}">$cat</td>'; }
            print '<td>', join(', ', sort by_area keys %{ $loc->{$mode}{$cat} }), qq'</td></tr>\n';
        }
    }
}

# name => "", num => ###, soundex => 0/1, dist => 0-1

sub fuzzysearch {
    my $search = shift;
    my $soundex = soundex $search;
    my ($pokes, $moves, $types) = ( [], [], [] );
    my $addmatch = sub {
        my ($i, $name, $array) = @_;
        my $dist = adistr(lc $search, lc $name);
        my $sex = ($soundex eq soundex $name) ? 1 : 0;
        push @$array, { name => $name, num => $i + 1, soundex => $sex, dist => abs $dist / (1+$sex) } if ($dist < .34 and $dist >= 0) or $sex;
    };

    for my $i (0 .. $#PokeNames) { $addmatch->($i, $PokeNames[$i], $pokes) }
    for my $i (0 .. $#MoveData) { $addmatch->($i, $MoveData[$i]{name}, $moves) }
    for my $t (@TypeNames) { $addmatch->($TypeData{$t}{internalid}, $t, $types) }

    return (pokemon => $pokes, moves => $moves, types => $types);
}

sub hashref_equal {
    my ($a, $b) = @_;
    if (scalar(keys %$a) != scalar(keys %$b)) { return 0; }
    if (sort keys %$a != sort keys %$b) { return 0; }
    for my $i (keys %$a) {
        if (ref $a->{$i} ne ref $b->{$i}) { return 0; }
        if (!ref $a->{$i} and $a->{$i} ne $b->{$i}) { return 0; }
        if (ref $a->{$i} eq 'ARRAY') { return &arrayref_equal($a->{$i}, $b->{$i}); }
        if (ref $a->{$i} eq 'HASH') { return &hashref_equal($a->{$i}, $b->{$i}); }
    }
    return 1;
}

sub arrayref_equal {
    my ($a, $b) = @_;
    if ($#$a != $#$b) { return 0; }
    for my $i (0 .. $#$a) {
        if (ref $a->[$i] ne ref $b->[$i]) { return 0; }
        if (!ref $a->[$i] and $a->[$i] ne $b->[$i]) { return 0; }
        if (ref $a->[$i] eq 'ARRAY') { return &arrayref_equal($a->[$i], $b->[$i]); }
        if (ref $a->[$i] eq 'HASH') { return &hashref_equal($a->[$i], $b->[$i]); }
    }
    return 1;
}

sub by_level { return (($$a[0] <=> $$b[0]) or ($MoveData[$$a[1]]{name} cmp $MoveData[$$b[1]]{name})) }


1;
