#################################################################################
# Ikonboard v3 by Jarvis Entertainment Group, Inc.
#
# No parts of this script can be used outside Ikonboard without prior consent.
#
# More information available from <ib-license@jarvisgroup.net>
# (c)2001 Jarvis Entertainment Group, Inc.
# 
# http://www.ikonboard.com
#
# Please Read the license for more information
#
#
# Search Functions.
#
#################################################################################
package Search::API::api_functions;
use strict;

#require Boardinfo;
#$iB::INFO = Boardinfo->new();

sub get_new {
    my $IN = { DB       => "",
               DATE     => "",
               FORUMS   => "",
               LIMIT    => 200,
               FILE_KEY => "",
               @_,
             };
    
    my $db   = $IN->{DB};
    my $tbl  = $db->prefix.'forum_topics';
    
    my $f_str;
    
    for (@{$IN->{FORUMS}}) {
        $f_str .= "'$_',";
    }
    
    $f_str =~ s:,$::;
    
    my $query = "SELECT TOPIC_ID FROM $tbl WHERE FORUM_ID IN($f_str) AND TOPIC_LAST_DATE > $IN->{DATE} ORDER BY TOPIC_LAST_DATE DESC LIMIT 0,$IN->{LIMIT}";
    
    my $got_results = 0;

    open SEARCH, ">".$iB::INFO->{'DB_DIR'}.'Temp/Searches'."/$IN->{FILE_KEY}" or die $!;
    print SEARCH time."\n";
    print SEARCH "new\n";
    print SEARCH "new\n";
    print SEARCH "new\n";
    
    my $sth = $db->parse_raw($query);
    die "mySQL error<br>".$db->error if $db->error;
    
    while (my $row = $db->get_row($sth)) {
        ++$got_results;
        print SEARCH $row->{TOPIC_ID}.",";
    }
    $db->done($sth);
    
    print SEARCH "\n$got_results";
    
    close SEARCH;

    # return the $got_results flag to indicate matches found or not
    
    return $got_results;
    
}


######################################################
# Prepare, execute and store the TOPIC_IDs of the returned
# query.
# Return the amount of matching topics
######################################################

sub run_query {
    my $IN = { 
                DB          => "",
                KEYWORDS    => "",
                PRUNE       => "",
                PRUNE_TYPE  => "",
                FORUMS      => [],
                SEARCH_IN   => "",
                SEARCH_TYPE => "",
                LIMIT       => 200,
                FILE_KEY    => "",
                @_
             };
             
    # Set a more friendly db handler.
    
    my $db   = $IN->{DB};
    my $tbl  = $db->prefix.'search_log';
    
    my $f_str;
    
    for (@{$IN->{FORUMS}}) {
        $f_str .= "'$_',";
    }
    
    $f_str =~ s:,$::;
    
    # Time to parse the query
    
    my $query = "SELECT distinct(TOPIC_ID) from $tbl WHERE FORUM_ID IN($f_str) AND (";
    
    while ($IN->{KEYWORDS} =~ m!(^|and|or)\s{1,}(\S+?)\s{1,}!isg) {
        if ($2 ne '') {
            my $keyword = $2;
            my $any_op  = $1;
            
            # Figure out if we're matching a word boundry, or we're using a wild card match
            $keyword = '\s*'.$keyword unless ($keyword =~ /^%/);
            $keyword = $keyword.'\s*' unless ($keyword =~ /%$/);
            # Swop SQL's % to a POSIX regexp .*
            $keyword =~ s:%:\.\*:g;
            # Make quotes safe (addslashes :D)
            $keyword =~ s:':\\':g;
            # make $any_op spaced
            $any_op = " $any_op ";
                          
            if ($IN->{SEARCH_IN} eq 'Post' or $iB::IN{'type'} eq 'name') {
                $query .= $IN->{SEARCH_TYPE} eq 'post' ? $any_op."POST REGEXP '$keyword'" : $any_op."MEMBER_NAME REGEXP '$keyword'";
            }
            elsif ($IN->{SEARCH_IN} eq 'titles') {
                $query .= $any_op."TOPIC_TITLE REGEXP '$keyword'";
            }
            elsif ($IN->{SEARCH_IN} eq 'all') {
                $query .= $any_op."(TOPIC_TITLE REGEXP '$keyword' or POST REGEXP '$keyword')";
            } else {
                # Must be a post only search then!
                $query .= $any_op."POST REGEXP '$keyword'";
            }
        }
    }
    
    #add the closing parethesis
    
    $query .= ")";

    # Add on the prune arg if needed
    if ($IN->{PRUNE} > 0) {
        my $gt_lt = $IN->{PRUNE_TYPE} eq 'older' ? "<" : ">";
        my $time = time - ($IN->{PRUNE} * 86400);
        $query .= " and DATE $gt_lt '$time'";
    }
    
    # add on the limit clause / order clause
    
    $query .= " ORDER BY DATE DESC LIMIT 0,$IN->{LIMIT}";

    # WHY USE A FLAT FILE!!
    # What's it got to do with you?!
    
    # Actually, we used to store the results in a DB table - but after it reached about
    # 200mb in size add the fact that the data is redundant after about an hour, it seemed
    #Ępointless stuffing up a table with topic ID's - so we use a flat file and destroy it later

    my $got_results = 0;

    open SEARCH, ">".$iB::INFO->{'DB_DIR'}.'Temp/Searches'."/$IN->{FILE_KEY}" or die $!;
    print SEARCH time."\n";
    print SEARCH "$IN->{KEYWORDS}\n";
    print SEARCH "$IN->{SEARCH_IN}\n";
    print SEARCH "$IN->{SEARCH_TYPE}\n";
    
    my $sth = $db->parse_raw($query);
    die "mySQL error<br>".$db->error if $db->error;
    
    while (my $row = $db->get_row($sth)) {
        ++$got_results;
        print SEARCH $row->{TOPIC_ID}.",";
    }
    $db->done($sth);
    
    print SEARCH "\n$got_results";
    
    close SEARCH;

    # return the $got_results flag to indicate matches found or not
    
    return $got_results;
    
}


sub parse_results {
    my $IN = {  DB           => "",  #var
                START        => "",  #int
                END          => "",  #int
                TOPIC_STRING => "",  #string
                KEYWORDS     => "",
                @_,
             };
             
    my $print;
    my $start = $IN->{START};
    my $end   = $IN->{END};
    my $db    = $IN->{DB};
    my $tbl   = $db->prefix.'forum_info';
    
    #Tidy up the keywords
    
    $IN->{KEYWORDS} =~ s!^\s+!!;
    $IN->{KEYWORDS} =~ s!\s+$!!g;
    $IN->{KEYWORDS} =~ s!\s!\+!g;
    
    my $forum_hash = {};
    
    my $sth = $db->parse_raw("SELECT FORUM_ID, FORUM_PROTECT, FORUM_VIEW_THREADS, FORUM_NAME FROM $tbl");
    die "mySQL error<br>".$db->error if $db->error;

    while (my $f = $db->get_row($sth)) {

        if ($f->{'FORUM_PROTECT'}) {
            next unless $iB::COOKIES->{ $iB::INFO->{'COOKIE_ID'}.'iBForum' . $f->{'FORUM_ID'} } eq $f->{'FORUM_PROTECT'};
        }
        
        if ($f->{'FORUM_VIEW_THREADS'} ne '*') {
            next unless grep { $_ == $iB::MEMBER->{'MEMBER_GROUP'} } (split /,/,$f->{'FORUM_VIEW_THREADS'});
        }

        $forum_hash->{ $f->{'FORUM_ID'} } = { 'FORUM_ID'   => $f->{'FORUM_ID'},
                                              'FORUM_NAME' => $f->{'FORUM_NAME'},
                                            };
    }
    
    $db->done($sth);
    
    # Split the string based on our start and end integers and form
    # a SQL usable IN statement
    
    my $in_stm;
    my $i = 0;
    for (split/,/, $IN->{TOPIC_STRING}) {
        ++$i;
        next unless $i >= $start;
        last if     $i >= $end;
        $in_stm .= "'$_',";
    }

    $in_stm =~ s:,$::;
    
    $tbl    = $db->prefix.'forum_topics';
    
    my $sth = $db->parse_raw("SELECT * FROM $tbl WHERE TOPIC_ID IN($in_stm) ORDER BY TOPIC_LAST_DATE DESC");
    die "mySQL error<br>".$db->error if $db->error;

    while (my $r = $db->get_row($sth)) {
        $r->{KEYWORDS}     = $IN->{KEYWORDS};
        $r->{'FORUM_ID'}   = $forum_hash->{ $r->{FORUM_ID} }->{'FORUM_ID'};
        $r->{'FORUM_NAME'} = $forum_hash->{ $r->{FORUM_ID} }->{'FORUM_NAME'};
        $print .= Search::API::api_global::do_row( $r ) if $r->{'TOPIC_TITLE'} ne '';
    }
    
    return $print;
}



1;