# ==================================================================
# Gossamer Threads Module Library - http://gossamer-threads.com/
#
#   GT::Search::MYSQL::VER3
#   Author  : Aki Mimoto
#   CVS Info :                          
#   $Id: VER3.pm,v 1.3 2004/08/28 03:53:49 jagerman Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# ==================================================================
#
# Description:
#   Class used to search indexed tables.
#

package GT::SQL::Search::MYSQL::VER3;
# ------------------------------------------------------------------------------
    use strict;
    use vars qw/ @ISA $ATTRIBS $VERSION $DEBUG $AUTOLOAD /;
    use GT::SQL::Search::Base::Search;
    @ISA = qw( GT::SQL::Search::Base::Search );

# ------------------------------------------------------------------------------
# Preamble information related to the object

    $DEBUG   = 0;
    $VERSION = sprintf "%d.%03d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/;
    $ATTRIBS = {
        min_word_size => 4
    };

sub _phrase_query {
# ------------------------------------------------------------------------------
    my $self    = shift;
    my $phrases = shift or return $_[0];
    my $results = shift || {};

    foreach my $phrase ( values %{$phrases} ) {
        $self->debug_dumper( "Unioning: ", $phrase ) if ($self->{_debug});

        my $tmp = {};
        foreach my $keyword ( @{ $phrase->{phrase}|| [] } ) {
            $tmp = $self->_get_words ( [ $keyword ], $tmp, 'intersect' );
            keys %$tmp or return {};
        }
        foreach my $key ( keys %$tmp ) { $results->{$key} += $tmp->{$key} }

    }

    return $results;
}

sub _get_phrase {
# ------------------------------------------------------------------------------
# one day change this so it does words properly
    return _get_words(@_);
}

sub _union_query {
# ------------------------------------------------------------------------------
    return _get_words(@_);
}

sub _intersect_query {
# ------------------------------------------------------------------------------
    my ( $self, $keywords, $results ) = @_;
    $keywords or return $results;

    foreach my $keyword ( keys %{ $keywords || {} } ) {
        $results = $self->_get_words ( [ $keyword ], $results, 'intersect' );
        keys %$results or return {};
    }

    return $results;
}

sub _phrase_intersect_query {
# ------------------------------------------------------------------------------
    my $self    = shift;
    my $phrases = shift or return $_[0];
    my $results = shift || {};

    my $tmp = $self->_phrase_query ( $phrases, $results );
    keys %$results or return $tmp;
    foreach my $key ( keys %$results ) {
        if ( $tmp->{$key} ) {
            $results->{$key} += $tmp->{$key};
        }
        else {
            delete $results->{$key}
        }
    }

    return $results;
}

sub _disjoin_query {
# ------------------------------------------------------------------------------
    my $self    = shift;
    my $words   = shift or return shift;
    my $results = shift || {};

    $results = $self->_get_words([ keys %{$words || {}} ], $results, 'disjoin' );

    return $results;
}

sub _phrase_disjoin_query {
# ------------------------------------------------------------------------------
    my $self    = shift;
    my $phrases = shift or return shift;
    my $results = shift || {};

    my $tmp = $self->_phrase_query ( $phrases, $results );
    keys %$results or return $tmp;
    foreach my $key ( keys %$results ) {
        $tmp->{$key} and delete $results->{$key};
    }
}

sub _get_words {
# ------------------------------------------------------------------------------
    my $self     = shift;
    my $words    = shift or return $_[0] || {};
    my $results  = shift || {};
    my $mode     = lc shift;

    my $tbl      = $self->{table} or $self->error( 'BADARGS', 'FATAL', 'Must have table object defined' );
    my $tname    = $tbl->name();
    my $wordlist = join " ", ( ref $words ? ( ref $words eq 'HASH' ? keys %$words : @$words ) : $words ) ;
    my ($pk)     = $tbl->pk;

    my %weights  = $tbl->_weight_cols();
    my $cols     = join(",", keys %weights);
    my $qwrds    = quotemeta( $wordlist );
    my $where    = ( $results and keys %$results )
        ? ("AND $pk IN(" . join(',', keys %$results) . ")")
        : '';
    my $query = qq!
        SELECT $pk, MATCH($cols) AGAINST ('$qwrds') AS SCORE
        FROM  $tname
        WHERE MATCH($cols) AGAINST ('$qwrds')
        $where
    !;
    my $sth = $tbl->do_query( $query ) or return;

    if ( $mode eq 'disjoin' ) {
        while ( my $result = $sth->fetchrow ) {
            delete $results->{$result};
        }
    }
    elsif ( $mode eq 'intersect' ) {
        my $tmp = {};
        while ( my $aref = $sth->fetchrow_arrayref ) {
            $tmp->{$aref->[0]} = $aref->[1];
        }
        if ( $results and keys %$results ) {
            while (my ($id, $score) = each %$results) {
                if (not defined $tmp->{$id}) {
                    delete $results->{$id};
                    next;
                }
                $results->{$id} += $score;
            }
        }
        else {
            $results = $tmp;
        }
    }
    else {
        while ( my $aref = $sth->fetchrow_arrayref ) {
            $results->{$aref->[0]} += $aref->[1];
        }
    }
    return $results;
}

1;
