package ModCP;
use strict;
#################################################################################
# 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
#+-----------------------------------------------------------------+
#
# ModCP: Moderation Control Panel
#
#################################################################################

BEGIN {
    require 'Lib/FUNC.pm';
    require 'iTextparser.pm';
    require 'Searchlog.pm';
    require 'Moderate.pm';
}

my $output      = FUNC::Output->new();
my $mem         = FUNC::Member->new();
my $std         = FUNC::STD->new();
my $txt         = iTextparser->new();
my $s_log       = Searchlog->new();
my $mod         = Moderate->new();
$ModCP::lang    = $std->LoadLanguage('ModCPWords');
$Moderate::lang = $std->LoadLanguage('ModerateWords');



sub new {
    my $pkg = shift;
    my $obj = { 'html' => undef, 'PASSED' => 0 };
    bless $obj, $pkg;
    return $obj;
}

################################################################
#
# ModSplash, print out the beginning mod CP screen
#
################################################################


sub mod_splash {
    my ($obj, $db) = @_;

    # Do we have a forum we're looking at?

    $obj->{html} = ModCPView::startcp();

    $iB::IN{'f'} ? $obj->_forum_splash($db) : $obj->_main_splash($db);

    $obj->{html} .= ModCPView::endcp();


}

sub read_post {
    my ($obj, $db) = @_;

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    my $p_data = $db->select( TABLE => 'mod_posts',
                              KEY   => $iB::IN{'ID'},
                            );
    my $print = ModCPView::read_post( $p_data );
    ++$obj->{bypass};
    $output->print_popup( STD    => $std,
                          OUTPUT => $print,
                          TITLE  => "iB::" . "$ModCP::lang->{'title'}",
                        );
}



sub _forum_splash {
    my ($obj, $db) = @_;

    # Are we a moderator of this forum?

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    $obj->{html} .= ModCPView::forum_splash( $forum_info);

    # Get the number of topics to preview
    my $topic_mod = $db->query( TABLE   => 'forum_topics',
                                ID      => $iB::IN{'f'},
                                WHERE   => "APPROVED == 0 and FORUM_ID == '$iB::IN{'f'}'",
                                COLUMNS => ['TOPIC_ID'],
                              );
    my $topic_count = scalar @{$topic_mod};

    # Get the number of posts to preview
    my $posts_mod = $db->query( TABLE   => 'mod_posts',
                                WHERE   => "FORUM_ID == '$iB::IN{'f'}' and TYPE ne 'new'",
                              );
    my $posts_count = scalar @{$posts_mod};

    # Print the topics to moderate header
    $obj->{html} .= ModCPView::topic_form_header( $topic_count );
    
    # Do we have any? If so, print out the form
    $obj->{html} .= $topic_count > 0 ? ModCPView::topic_form() : ModCPView::topic_none();

    # Print the posts to moderate header
    $obj->{html} .= ModCPView::post_form_header( $posts_count );
    
    # Do we have any? If so, print out the form
    $obj->{html} .= $posts_count > 0 ? ModCPView::post_form() : ModCPView::post_none();

    $obj->{html} .= ModCPView::end_forum_splash();
}

################################################################
#
# DELETE TOPICS
#
################################################################

sub delete {
    my ($obj, $db) = @_;

    # Are we a moderator of this forum?

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    $obj->{html} .= ModCPView::startcp();
    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;
    $obj->{html} .= ModCPView::forum_splash( $forum_info);
    $obj->{html} .= ModCPView::delete_form_header(); 
    $obj->{html} .= ModCPView::end_forum_splash();
    $obj->{html} .= ModCPView::endcp();
}
sub process_delete {
    my ($obj, $db) = @_;

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) and defined($iB::IN{'LIMIT'}) );

    # Build the query...
    my $date_cut = " and TOPIC_START_DATE > ".(time-(60*60*24*$iB::IN{'DAYS'}));
    my $order    = $iB::IN{'ORDER'} eq 'asc' ? 'A-Z' : 'Z-A';

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );
    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    # Get the topics...
    my $topics = $db->query( TABLE    => 'forum_topics',
                             ID       => $iB::IN{'f'},
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 1$date_cut",
                             SORT_KEY => 'TOPIC_LAST_DATE',
                             SORT_BY  => $order,
                             RANGE    => "0 to $iB::IN{'LIMIT'}",
                           );

    unless (scalar(@{$topics}) > 0) {
        ++$obj->{bypass};
        $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=delete" );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $forum_info->{'search_type'} = 'do_delete';
    $obj->{html} .= ModCPView::topic_header( $forum_info );

    for my $t (@{$topics}) {
        # Convert unix time to human readable
        $t->{'TOPIC_START_DATE'} = $std->get_date( TIME => $t->{'TOPIC_START_DATE'}, METHOD => 'LONG' );
        $t->{'TOPIC_LAST_DATE'}  = $std->get_date( TIME => $t->{'TOPIC_LAST_DATE'},  METHOD => 'LONG' );

        my $select = qq!<select name='CHOICE_$t->{'TOPIC_ID'}' class='forminput'>!;
        $select .= qq!<option value='leave' selected>$ModCP::lang->{'c_leave'}</option><option value='delete'>* $ModCP::lang->{'c_delete'} *</option>!;
                 
        $t->{'SELECT'} = $select . "</select>";

        $t->{'LAST_POSTER'} = ($t->{'TOPIC_LAST_POSTER'} != 0)   ? qq[<b><a href='$iB::INFO->{'BOARD_URL'}/ikonboard.$iB::INFO->{'CGI_EXT'}?s=$iB::SESSION;act=Profile;CODE=03;MID=$t->{'TOPIC_LAST_POSTER'}'>$t->{'TOPIC_LASTP_N'}</a></b>]
                                                                 : qq[-$t->{'TOPIC_LASTP_N'}-];

        $obj->{html} .= ModCPView::render_opentopic( $t );
    }


    $obj->{html} .= ModCPView::topic_footer();
    $obj->{html} .= ModCPView::endcp();
}

sub do_delete {
    my ($obj, $db) = @_;

    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );


    # Sort out the form data.
    my @topic_ids = grep { /^CHOICE_(\d+)$/ } $iB::CGI->param();

    my $global = { leave => 0, delete => 0 };

    my $count  = { TOPICS => 0, POSTS => 0 };

    for my $id (@topic_ids) {
        $id  =~ /^CHOICE_(\d+)$/;
        $id  = $1;
        next unless $id;
        my $choice = $iB::CGI->param( 'CHOICE_'.$id );
        next unless $choice;
        ++$global->{ $choice } and next if $choice eq 'leave';

        my $topic = $db->select( TABLE => 'forum_topics',
                                 ID     => $iB::IN{'f'},
                                 KEY    => $id,
                               );


        # If we are deleting..
        $db->delete( TABLE  => 'forum_topics',
                     ID     => $iB::IN{'f'},
                     KEY    => $id,
                   );

        $db->delete(  TABLE  => 'forum_polls',
                      WHERE  => "POLL_ID == $id and FORUM_ID == $iB::IN{'f'}"
                   );
    
        $db->delete(  TABLE  => 'forum_poll_voters',
                      WHERE  => "POLL_ID == $id and FORUM_ID == $iB::IN{'f'}"
                   );
    
        $db->delete(  TABLE  => 'forum_posts',
                      DBID   => 'f'.$iB::IN{'f'},
                      ID     => $id,
                      WHERE  => "TOPIC_ID == $id and FORUM_ID == $iB::IN{'f'} and POST_ID > '0'",
                    );
    
        $db->delete(  TABLE  => 'search_log',
                      ID     => $iB::IN{'f'},
                      WHERE  => qq[FORUM_ID == $iB::IN{'f'} and TOPIC_ID == $id],
                   );

        
        ++$global->{ 'delete' };
        $count->{'POSTS'}  += $topic->{'TOPIC_POSTS'};
        $count->{'TOPICS'} += 1;
    }

    # Fix up the forum...
    if ($global->{ 'delete' }) {
        $obj->_reset_forum( FORUM      => $iB::IN{'f'},
                            DEL_POSTS  => $count->{'POSTS'},
                            DEL_TOPICS => $count->{'TOPICS'},
                            DB         => $db,
                          );
        $obj->_reset_stats(
                            DEL_POSTS  => $count->{'POSTS'},
                            DEL_TOPICS => $count->{'TOPICS'},
                          );
        
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $obj->{html} .= ModCPView::show_delete_results( $global );
    $obj->{html} .= ModCPView::endcp();
}

################################################################
#
# PRUNE FORUM
#
################################################################

sub prune {
    my ($obj, $db) = @_;

    # Are we a moderator of this forum?

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };

        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless $obj->{moderator}->{ $iB::IN{'f'} }->{'MASS_PRUNE'};
    }

    $obj->{html} .= ModCPView::startcp();
    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;
    $obj->{html} .= ModCPView::forum_splash( $forum_info);
    $obj->{html} .= ModCPView::prune_form_header(); 
    $obj->{html} .= ModCPView::end_forum_splash();
    $obj->{html} .= ModCPView::endcp();
}

sub process_prune {
    my ($obj, $db) = @_;

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    my $st = $iB::IN{st} || 0;

    my $total = $iB::IN{PAGE} + ($st - 1);

    $iB::IN{RUN} = $st + $iB::IN{PAGE};

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) );

    # Build the query...
    my $date_cut = " and TOPIC_LAST_DATE < ".(time-(60*60*24*$iB::IN{'DAYS'}));


    # First of all, we need to see how many topics we want to grab...

    if ($st == 0 and $iB::IN{PROCESS} != 1) {
        my $topics = $db->query( TABLE    => 'forum_topics',
                                 ID       => $iB::IN{'f'},
                                 COLUMNS  => ['TOPIC_ID'],
                                 WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 1$date_cut",
                               );
        my $topic_total = scalar(@{$topics});

        unless ($topic_total > 0) {
            ++$obj->{bypass};
            $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=prune" );
        }

        # else, just redirect.

        $ModCP::lang->{s_pstart} =~ s/<#TOTAL#>/$topic_total/;
        $output->redirect_screen( TEXT => $ModCP::lang->{s_pstart}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=process_prune&DAYS=$iB::IN{'DAYS'}&PAGE=$iB::IN{PAGE}&st=$st&PROCESS=1&ORIG=$topic_total" );
    }

    # Get the topics...
    my $topics = $db->query( TABLE    => 'forum_topics',
                             ID       => $iB::IN{'f'},
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 1$date_cut",
                             RANGE    => "0 to ".($iB::IN{PAGE} - 1),
                           );


    my $forum_info = $db->select( TABLE  => 'forum_info',
                                  KEY    => $iB::IN{'f'},
                                );

    my $global = { leave => $forum_info->{'FORUM_TOPICS'}, delete => 0 };

    my $count  = { TOPICS => 0, POSTS => 0 };

    for my $id (@{$topics}) {
        next unless $id;

        $id = $id->{'TOPIC_ID'};

        my $topic = $db->select( TABLE => 'forum_topics',
                                 ID     => $iB::IN{'f'},
                                 KEY    => $id,
                               );

        # If we are deleting..
        $db->delete( TABLE  => 'forum_topics',
                     ID     => $iB::IN{'f'},
                     KEY    => $id,
                   );

        if ($topic->{POLL_STATE} or $topic->{LAST_VOTE}) {
            $db->delete(  TABLE  => 'forum_polls',
                          WHERE  => "POLL_ID == $id and FORUM_ID == $iB::IN{'f'}"
                       );
        
            $db->delete(  TABLE  => 'forum_poll_voters',
                          WHERE  => "POLL_ID == $id and FORUM_ID == $iB::IN{'f'}"
                       );
        }
        $db->delete(  TABLE  => 'forum_posts',
                      DBID   => 'f'.$iB::IN{'f'},
                      ID     => $id,
                      WHERE  => "TOPIC_ID == $id and FORUM_ID == $iB::IN{'f'}",
                    );
    
        $db->delete(  TABLE  => 'search_log',
                      ID     => $iB::IN{'f'},
                      WHERE  => qq[FORUM_ID == $iB::IN{'f'} and TOPIC_ID == $id],
                   );

        
        ++$global->{'delete'};
        --$global->{'leave'};
        $count->{'POSTS'}  += $topic->{'TOPIC_POSTS'};
        $count->{'TOPICS'} += 1;

    }

    # If we are done..

    #GL=$global->{leave}&GD=$global->{delete}&CT=$count->{TOPICS}&CP=$count->{POSTS}

    $global->{delete} += $iB::IN{GD};
    $count->{POSTS}   += $iB::IN{CP};
    $count->{TOPICS}  += $iB::IN{CT};

    if ( (scalar(@{$topics}) < 1) or ($iB::IN{RUN} >= $iB::IN{ORIG}) ) {
        # Fix up the forum...

        if ($global->{ 'delete' }) {
            $obj->_reset_forum( FORUM      => $iB::IN{'f'},
                                DEL_POSTS  => $count->{'POSTS'},
                                DEL_TOPICS => $count->{'TOPICS'},
                                DB         => $db,
                              );
            $obj->_reset_stats(
                                DEL_POSTS  => $count->{'POSTS'},
                                DEL_TOPICS => $count->{'TOPICS'},
                              );
            
        }
    
        $obj->{html} = ModCPView::startcp();
        $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
        $obj->{html} .= ModCPView::show_delete_results( $global );
        $obj->{html} .= ModCPView::endcp();
    } else {
        # if not, redirect..
    
        $ModCP::lang->{s_refresh} =~ s/<#NUM#>/$iB::IN{RUN}/;
        $ModCP::lang->{s_refresh} =~ s/<#TOTAL#>/$iB::IN{ORIG}/;
    
        $output->redirect_screen( TEXT => $ModCP::lang->{s_refresh}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=process_prune&DAYS=$iB::IN{'DAYS'}&PAGE=$iB::IN{PAGE}&st=$iB::IN{RUN}&PROCESS=1&ORIG=$iB::IN{ORIG}&RUN=$iB::IN{RUN}&GL=$global->{leave}&GD=$global->{delete}&CT=$count->{TOPICS}&CP=$count->{POSTS}" );

    }
}

################################################################
#
# OPEN  /  CLOSE
#
################################################################


sub open_close_topics {
    my ($obj, $db) = @_;

    # Are we a moderator of this forum?

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    $obj->{html} .= ModCPView::startcp();
    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;
    $obj->{html} .= ModCPView::forum_splash( $forum_info);
    $obj->{html} .= ModCPView::open_form_header(); 
    $obj->{html} .= ModCPView::end_forum_splash();
    $obj->{html} .= ModCPView::endcp();
}

sub process_open_close_topics {
    my ($obj, $db) = @_;

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) and defined($iB::IN{'LIMIT'}) );

    # Build the query...
    my $date_cut = " and TOPIC_START_DATE > ".(time-(60*60*24*$iB::IN{'DAYS'}));
    my $order    = $iB::IN{'ORDER'} eq 'asc' ? 'A-Z' : 'Z-A';

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );
    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    # Get the topics...
    my $topics = $db->query( TABLE    => 'forum_topics',
                             ID       => $iB::IN{'f'},
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 1$date_cut",
                             SORT_KEY => 'TOPIC_START_DATE',
                             SORT_BY  => $order,
                             RANGE    => "0 to $iB::IN{'LIMIT'}",
                           );

    unless (scalar(@{$topics}) > 0) {
        ++$obj->{bypass};
        $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=open" );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $forum_info->{'search_type'} = 'do_openclose';
    $obj->{html} .= ModCPView::topic_header( $forum_info );

    for my $t (@{$topics}) {
        # Convert unix time to human readable
        $t->{'TOPIC_START_DATE'} = $std->get_date( TIME => $t->{'TOPIC_START_DATE'}, METHOD => 'LONG' );
        $t->{'TOPIC_LAST_DATE'}  = $std->get_date( TIME => $t->{'TOPIC_LAST_DATE'},  METHOD => 'LONG' );

        my $select = qq!<select name='CHOICE_$t->{'TOPIC_ID'}' class='forminput'>!;
        $select .= $t->{'TOPIC_STATE'} eq 'open'
                 ? qq!<option value='open' selected>$ModCP::lang->{'st_open'}</option><option value='closed'>$ModCP::lang->{'st_close'}</option>!
                 : qq!<option value='open'>$ModCP::lang->{'st_open'}</option><option value='closed' selected>$ModCP::lang->{'st_close'}</option>!;

        $t->{'SELECT'} = $select . "</select>";

        $t->{'LAST_POSTER'} = ($t->{'TOPIC_LAST_POSTER'} != 0)   ? qq[<b><a href='$iB::INFO->{'BOARD_URL'}/ikonboard.$iB::INFO->{'CGI_EXT'}?s=$iB::SESSION;act=Profile;CODE=03;MID=$t->{'TOPIC_LAST_POSTER'}'>$t->{'TOPIC_LASTP_N'}</a></b>]
                                                                 : qq[-$t->{'TOPIC_LASTP_N'}-];

        $obj->{html} .= ModCPView::render_opentopic( $t );
    }


    $obj->{html} .= ModCPView::topic_footer();
    $obj->{html} .= ModCPView::endcp();
}

sub do_openclose {
    my ($obj, $db) = @_;

    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    # Sort out the form data.
    my @topic_ids = grep { /^CHOICE_(\d+)$/ } $iB::CGI->param();

    my $global = { open => 0, closed => 0 };

    for my $id (@topic_ids) {
        $id  =~ /^CHOICE_(\d+)$/;
        $id  = $1;
        next unless $id;
        my $choice = $iB::CGI->param( 'CHOICE_'.$id );
        next unless $choice;
        $db->update( TABLE  => 'forum_topics',
                     ID     => $iB::IN{'f'},
                     KEY    => $id,
                     VALUES => { TOPIC_STATE => $choice },
                   );
        
        ++$global->{ $choice };
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $obj->{html} .= ModCPView::show_open_results( $global );
    $obj->{html} .= ModCPView::endcp();
}


################################################################
#
# MOVE TOPICS
#
################################################################

sub move_topics {
    my ($obj, $db) = @_;

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE => 'moderate_no_permission'
                   ) unless $obj->{moderator}->{ $iB::IN{'f'} }->{'MASS_MOVE'};
    
        # Are we a moderator of this forum?
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    $obj->{html} .= ModCPView::startcp();
    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;
    $obj->{html} .= ModCPView::forum_splash( $forum_info);
    $obj->{html} .= ModCPView::move_form_header(); 
    $obj->{html} .= ModCPView::end_forum_splash();
    $obj->{html} .= ModCPView::endcp();
}

sub process_move {
    my ($obj, $db) = @_;

    unless ($obj->{type} eq 'all') {
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE => 'moderate_no_permission'
                   ) unless $obj->{moderator}->{ $iB::IN{'f'} }->{'MASS_MOVE'};
    
        # Are we a moderator of this forum?
        $std->Error( DB      => $db,
                     LEVEL   => 1,
                     MESSAGE =>'moderate_no_permission'
                   ) unless exists $obj->{moderator}->{ $iB::IN{'f'} };
    }

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    my $html = qq[ <select name='destination' class='forminput'>];

    require $iB::INFO->{'IKON_DIR'}.'Data/ForumJump.pm';
    my $Forums = ForumJump->new();

    for (sort { $a <=> $b } keys %{$Forums}) {
        if ($Forums->{$_}[0] eq 'c') {
            if ($Forums->{$_}[3] ne '*') {
                next unless grep { $_ == $iB::MEMBER->{'MEMBER_GROUP'} } (split (/,/, $Forums->{$_}[3]) );
            }
            my $dash = '-' x length($Forums->{$_}[2]);
            $html .= qq[<option value="">&nbsp;\n
                        <option value="">&gt;$Forums->{$_}[2]\n
                        <option value="">&nbsp;&nbsp;$dash\n
                       ];
        } elsif ($Forums->{$_}[0] eq 'f') {
            if ($Forums->{$_}[3] ne '*') {
                next unless grep { $_ == $iB::MEMBER->{'MEMBER_GROUP'} } (split (/,/, $Forums->{$_}[3]) );
            }
            $html .= qq[<option value="$Forums->{$_}[1]">&nbsp;&nbsp;&nbsp;+- $Forums->{$_}[2]\n];
        }
    }

    $html .= qq[</select>\n];

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) and defined($iB::IN{'LIMIT'}) );

    # Build the query...
    my $date_cut = " and TOPIC_START_DATE > ".(time-(60*60*24*$iB::IN{'DAYS'}));
    my $order    = $iB::IN{'ORDER'} eq 'asc' ? 'A-Z' : 'Z-A';

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );
    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    # Get the topics...
    my $topics = $db->query( TABLE    => 'forum_topics',
                             ID       => $iB::IN{'f'},
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 1$date_cut",
                             SORT_KEY => 'TOPIC_START_DATE',
                             SORT_BY  => $order,
                             RANGE    => "0 to $iB::IN{'LIMIT'}",
                           );

    unless (scalar(@{$topics}) > 0) {
        ++$obj->{bypass};
        $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}&CODE=move" );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $forum_info->{'search_type'} = 'do_move';
    $obj->{html} .= ModCPView::move_ops( $html, $forum_info->{'FORUM_NAME'} );
    $obj->{html} .= ModCPView::topic_header( $forum_info );


    for my $t (@{$topics}) {
        # Convert unix time to human readable
        $t->{'TOPIC_START_DATE'} = $std->get_date( TIME => $t->{'TOPIC_START_DATE'}, METHOD => 'LONG' );
        $t->{'TOPIC_LAST_DATE'}  = $std->get_date( TIME => $t->{'TOPIC_LAST_DATE'},  METHOD => 'LONG' );

        my $select = qq!<select name='CHOICE_$t->{'TOPIC_ID'}' class='forminput'>!;
        $select .= qq!<option value='leave' selected>$ModCP::lang->{'c_leave'}</option><option value='move'>$ModCP::lang->{'st_move'}</option>!;


        $t->{'SELECT'} = $select . "</select>";

        $t->{'LAST_POSTER'} = ($t->{'TOPIC_LAST_POSTER'} != 0)   ? qq[<b><a href='$iB::INFO->{'BOARD_URL'}/ikonboard.$iB::INFO->{'CGI_EXT'}?s=$iB::SESSION;act=Profile;CODE=03;MID=$t->{'TOPIC_LAST_POSTER'}'>$t->{'TOPIC_LASTP_N'}</a></b>]
                                                                 : qq[-$t->{'TOPIC_LASTP_N'}-];

        $obj->{html} .= ModCPView::render_opentopic( $t );
    }


    $obj->{html} .= ModCPView::topic_footer();
    $obj->{html} .= ModCPView::endcp();
}

sub do_move {
    my ($obj, $db) = @_;

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE => 'move_no_forum'
               ) unless defined $iB::IN{'destination'};

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE => 'move_no_source'
               ) unless defined $iB::IN{'f'};


    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE => 'move_same_forum'
               ) if $iB::IN{'f'} == $iB::IN{'destination'};

    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    # Sort out the form data.
    my @topic_ids = grep { /^CHOICE_(\d+)$/ } $iB::CGI->param();
    my @real_ids;


    my $global = { leave => 0, move => 0 };

    for my $id (@topic_ids) {
        $id  =~ /^CHOICE_(\d+)$/;
        $id  = $1;
        next unless $id;
        my $choice = $iB::CGI->param( 'CHOICE_'.$id );
        next unless $choice;
        if ($choice eq 'move') {
            push @real_ids, $id;
        }
        ++$global->{ $choice };
    }

    my $info = $mod->move_topic( SOURCE       => $iB::IN{'f'},
                                 DESTINATION  => $iB::IN{'destination'},
                                 TOPICS       => \@real_ids,
                                 LINK         => $iB::IN{'leave'},
                                 DB           => $db,
                               );

    $obj->_reset_forum( FORUM      => $iB::IN{'f'},
                        DB         => $db,
                        ADD_POSTS  => $info->{'S_TOPICS'},
                        ADD_TOPICS => $info->{'S_POSTS'},
                      );

    $obj->_reset_forum( FORUM      => $iB::IN{'destination'},
                        DB         => $db,
                        ADD_POSTS  => $info->{'D_TOPICS'},
                        ADD_TOPICS => $info->{'D_POSTS'},
                      );

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $obj->{html} .= ModCPView::show_move_results( $global );
    $obj->{html} .= ModCPView::endcp();

}

################################################################
#
# TOPIC / POST PROCESSING
#
################################################################

sub topic_search {
    my ($obj, $db) = @_;

    if ($iB::IN{'POSTS'}) {
        $obj->post_search($db);
    }

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) and defined($iB::IN{'LIMIT'}) );

    # Build the query...
    my $date_cut = " and TOPIC_START_DATE > ".(time-(60*60*24*$iB::IN{'DAYS'}));
    my $order    = $iB::IN{'ORDER'} eq 'asc' ? 'A-Z' : 'Z-A';

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );
    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    # Get the topics...
    my $topics = $db->query( TABLE    => 'forum_topics',
                             ID       => $iB::IN{'f'},
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and APPROVED == 0$date_cut",
                             SORT_KEY => 'TOPIC_START_DATE',
                             SORT_BY  => $order,
                             RANGE    => "0 to $iB::IN{'LIMIT'}",
                           );

    unless (scalar(@{$topics}) > 0) {
        ++$obj->{bypass};
        $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}" );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $forum_info->{'search_type'} = 'process_topics';
    $obj->{html} .= ModCPView::search_header( $forum_info );

    for my $t (@{$topics}) {
        # Convert unix time to human readable
        $t->{'TOPIC_START_DATE'} = $std->get_date( TIME => $t->{'TOPIC_START_DATE'}, METHOD => 'LONG' );
        $t->{'TOPIC_LAST_DATE'}  = $std->get_date( TIME => $t->{'TOPIC_LAST_DATE'},  METHOD => 'LONG' );

        # Can we delete queued topics?
        if ($obj->{moderator}->{ $iB::IN{'f'} }->{'TOPIC_Q'} or $obj->{type} eq 'all') {
            $t->{'DELETE'} = qq!<option value='DELETE' selected>$ModCP::lang->{'c_delete'}</option>!;
        }

        # Get the corresponding post
        my $post = $db->query(  TABLE  => 'mod_posts',
                                MATCH  => 'ONE',
                                WHERE  => "TOPIC_ID == '$t->{'TOPIC_ID'}' and TYPE eq 'new'",
                             );
        $post->{'POST'} = substr( $post->{'POST'}, 0, 200 ) . '...';
        $obj->{html} .= ModCPView::render_newtopic( { TOPIC => $t, POST => $post } );
    }


    $obj->{html} .= ModCPView::search_footer();
    $obj->{html} .= ModCPView::endcp();
}


sub post_search {
    my ($obj, $db) = @_;

    if ($iB::IN{'TOPICS'}) {
        $obj->topic_search($db);
    }

    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;
    $iB::IN{'DAYS'} =~ s!^(\d+)$!$1!g;

    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'please_complete_form'
               ) unless ( defined($iB::IN{'DAYS'}) and defined($iB::IN{'LIMIT'}) );

    # Build the query...
    my $date_cut = " and POST_DATE > ".(time-(60*60*24*$iB::IN{'DAYS'}));
    my $order    = $iB::IN{'ORDER'} eq 'asc' ? 'A-Z' : 'Z-A';

    # Get the forum info
    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );
    $ModCP::lang->{'f_moderate_t'} =~ s!<# FORUM NAME #>!$forum_info->{'FORUM_NAME'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# POSTS #>!$forum_info->{'FORUM_POSTS'}!i;
    $ModCP::lang->{'f_moderate_t'} =~ s!<# TOPICS #>!$forum_info->{'FORUM_TOPICS'}!i;

    # Get the topics...
    my $posts  = $db->query( TABLE    => 'mod_posts',
                             WHERE    => "FORUM_ID == $iB::IN{'f'} and TYPE ne 'new'$date_cut",
                             SORT_KEY => 'POST_DATE',
                             SORT_BY  => $order,
                             RANGE    => "0 to $iB::IN{'LIMIT'}",
                           );



    unless (scalar(@{$posts}) > 0) {
        ++$obj->{bypass};
        $output->redirect_screen( TEXT => $ModCP::lang->{'no_matches'}, URL => "act=ModCP&f=$iB::IN{'f'}" );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $forum_info->{'search_type'} = 'process_posts';
    $obj->{html} .= ModCPView::search_header( $forum_info );

    # Set up a topics cache to save queries
    my $topic_cache = {};

    for my $p (@{$posts}) {
        if ( $topic_cache->{ $p->{'TOPIC_ID'} } ) {
            push @{ $topic_cache->{ $p->{'TOPIC_ID'} } }, $p;
        } else {
             $topic_cache->{ $p->{'TOPIC_ID'} } = [];
             push @{ $topic_cache->{ $p->{'TOPIC_ID'} } }, $p;
        }
    }


    for my $t (keys %{ $topic_cache }) {
        my $this_topic = $db->select( TABLE  => 'forum_topics',
                                      ID     => $iB::IN{'f'},
                                      KEY    => $t,
                                    );
        # Convert unix time to human readable
        $this_topic->{'TOPIC_START_DATE'} = $std->get_date( TIME => $this_topic->{'TOPIC_START_DATE'}, METHOD => 'LONG' );
        $this_topic->{'TOPIC_LAST_DATE'}  = $std->get_date( TIME => $this_topic->{'TOPIC_LAST_DATE'},  METHOD => 'LONG' );

        # Can we delete queued topics?
        if ($obj->{moderator}->{ $iB::IN{'f'} }->{'TOPIC_Q'} or $obj->{type} eq 'all') {
            $this_topic->{'DELETE'} = qq!<option value='DELETE' selected>$ModCP::lang->{'c_delete'}</option>!;
        }

        $obj->{html} .= ModCPView::render_topic_title( $this_topic );

        # loop through the posts to print
        for my $i (@{ $topic_cache->{ $t } }) {
            if ($i->{'AUTHOR_TYPE'}) {
                my $member = $db->select( TABLE => 'member_profiles',
                                          KEY   => $i->{'AUTHOR'},
                                        );
                $i->{'MEMBER_NAME'} = qq!<a href="$iB::INFO->{'BOARD_URL'}/ikonboard.$iB::INFO->{'CGI_EXT'}?s=$iB::SESSION;act=Profile;CODE=03;MID=$i->{'AUTHOR'}" target='_blank'><b><$member->{'MEMBER_NAME'}</b></a>!;
                undef $member;
            } else {
                $i->{'MEMBER_NAME'} = $i->{'AUTHOR'};
            }
            $i->{'POST'}       = substr( $i->{'POST'}, 0, 200 ) . '...';
            $i->{'POST_DATE'}  = $std->get_date( TIME => $i->{'POST_DATE'},  METHOD => 'LONG' );
            $obj->{html} .= ModCPView::render_topic_post( { POST => $i, TOPIC => $this_topic } );
        }
    }
    $obj->{html} .= ModCPView::search_footer();
    $obj->{html} .= ModCPView::endcp();
}


sub process_posts {
    my ($obj, $db) = @_;

    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    # Sort out the form data.
    my @post_ids = grep { /^CHOICE_(\d+)$/ } $iB::CGI->param();

    # Lets sort them into topic order.
    my $topic_ids = {};

    for my $i ( @post_ids ) {
        $i               =~ /^CHOICE_(\d+)$/;
        my $modpost_id   = $1;
        my $realpost_id  = $iB::CGI->param('POST_'   .$modpost_id);
        my $realtopic_id = $iB::CGI->param('TOPIC_'  .$modpost_id);
        my $choice       = $iB::CGI->param('CHOICE_' .$modpost_id);
        if ($topic_ids->{ $realtopic_id }) {
            push @{ $topic_ids->{ $realtopic_id } }, {
                                                        MODPOST_ID  => $modpost_id,
                                                        REALPOST_ID => $realpost_id,
                                                        CHOICE      => $choice,
                                                     };
        } else {
            $topic_ids->{ $realtopic_id } = [ ];
            push @{ $topic_ids->{ $realtopic_id } }, {
                                                        MODPOST_ID  => $modpost_id,
                                                        REALPOST_ID => $realpost_id,
                                                        CHOICE      => $choice,
                                                     };
        }
    } 

    # Set up some counters

    my $global = {
                   APPROVED => 0,
                   LEFT     => 0,
                   DELETED  => 0,
                 };

    my $added_posts = {};
    # First, lets sort out the posts.
    for my $i (keys %{ $topic_ids }) {

        my $t_data = $db->select( TABLE  => 'forum_topics',
                                  ID     => $iB::IN{'f'},
                                  KEY    => $i,
                                );
        for my $t (@{ $topic_ids->{ $i } }) {

            my $topic_id  = $i;
            my $post_id   = $t->{'MODPOST_ID'};
            my $r_post_id = $t->{'REALPOST_ID'};
            my $choice    = $t->{'CHOICE'};
            $added_posts->{ $t } = {
                                     ADDED_POSTS      => 0,
                                     LAST_POSTER_NAME => "",
                                     LAST_POSTER_ID   => "",
                                     LAST_POST_TIME   => "",
                                   };
            # Did we choose to leave this post alone?
            ++$global->{'LEFT'} and next if $choice eq 'LEAVE';
            if ($choice eq 'DELETE') {
                ++$global->{'DELETED'};
                $db->delete( TABLE => 'mod_posts',
                             KEY   => $post_id,
                           );
                $db->delete( TABLE  => 'forum_posts',
                             DBID   => 'f'.$iB::IN{'f'},
                             ID     => $topic_id,
                             KEY    => $r_post_id,
                           );
            } elsif ($choice eq 'APPROVE') {
                ++$global->{'APPROVED'};
                my $p_data = $db->select( TABLE => 'mod_posts',
                                          KEY   => $post_id,
                                        );

                $db->update( TABLE  => 'forum_posts',
                             DBID   => 'f'.$iB::IN{'f'},
                             ID     => $topic_id,
                             KEY    => $r_post_id,
                             VALUES => { QUEUED    => 0 },
                           );

                $db->delete( TABLE => 'mod_posts',
                             KEY   => $post_id,
                           );
                # Update the search records
                $s_log->compile_entry(     DB    => $db,
                                           TOPIC => $t_data,
                                           FORUM => $forum_info,
                                           POST  => $p_data,
                                     );

                # Sort out our topic stuff
                ++$added_posts->{ $i }->{'ADDED_POSTS'};
                if ($p_data->{'POST_DATE'} > $added_posts->{ $i }->{'LAST_POST_TIME'}) {
                    $added_posts->{ $i }->{'LAST_POST_TIME'}   = $p_data->{'POST_DATE'};
                    $added_posts->{ $i }->{'LAST_POSTER_NAME'} = $p_data->{'AUTHOR'};
                }

                # Update the members post count.
                if ($p_data->{'AUTHOR_TYPE'}) {
                    my $member = $db->select( TABLE  => 'member_profiles',
                                              KEY    => $p_data->{'AUTHOR'},
                                            );
                    ++$member->{'MEMBER_POSTS'};
                    $db->update( TABLE  => 'member_profiles',
                                 KEY    => $p_data->{'AUTHOR'},
                                 VALUES => { MEMBER_POSTS => $member->{'MEMBER_POSTS'} }
                               );
                    # If it's a member, and it's to be used in the last post info
                    # column, we'd better update our hash for the member ID and name.
                    if ($p_data->{'POST_DATE'} == $added_posts->{ $i }->{'LAST_POST_TIME'}) {
                        $added_posts->{ $i }->{'LAST_POSTER_NAME'} = $member->{'MEMBER_NAME'};
                        $added_posts->{ $i }->{'LAST_POSTER_ID'}   = $member->{'MEMBER_ID'};
                    }
                }
            }
        }
    }

    # Now lets update each topic with the info we stored in our topic specfic hash reference

    for my $k (keys %{ $topic_ids }) {

        if ($added_posts->{ $k }->{'ADDED_POSTS'}) {
            my $t_data = $db->select( TABLE  => 'forum_topics',
                                      ID     => $iB::IN{'f'},
                                      KEY    => $k,
                                    );
            $t_data->{'TOPIC_POSTS'}      += $added_posts->{ $k }->{'ADDED_POSTS'};
            $t_data->{'TOPIC_LAST_DATE'}   = $added_posts->{ $k }->{'LAST_POST_TIME'};
            $t_data->{'TOPIC_LAST_POSTER'} = $added_posts->{ $k }->{'LAST_POSTER_ID'};
            $t_data->{'TOPIC_LASTP_N'}     = $added_posts->{ $k }->{'LAST_POSTER_NAME'};
            
            $db->update( TABLE  => 'forum_topics',
                         ID     => $iB::IN{'f'},
                         KEY    => $k,
                         VALUES => $t_data,
                       );
        }
    }
    

    if ($global->{'APPROVED'}) {
        $obj->_reset_forum( FORUM      => $iB::IN{'f'},
                            ADD_POSTS  => $global->{'APPROVED'},
                            ADD_TOPICS => 0,
                            DB         => $db,
                          );
        $obj->_reset_stats(
                            ADD_POSTS  => $global->{'APPROVED'},
                            ADD_TOPICS => 0,
                          );
        
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $obj->{html} .= ModCPView::show_post_results( $global );
    $obj->{html} .= ModCPView::endcp();

}



sub process_topics {
    my ($obj, $db) = @_;

    my $forum_info = $obj->LoadForum( $db, $iB::IN{'f'} );

    # Sort out the form data.
    my @topic_ids = grep { /^CHOICE_(\d+)$/ } $iB::CGI->param();

    # Set up some counters

    my $count = {
                  APPROVED => 0,
                  LEFT     => 0,
                  DELETED  => 0,
                };

    for my $i(@topic_ids) {
        $i             =~ /^CHOICE_(\d+)$/;
        my $topic_id   = $1;
        my $post_id    = $iB::CGI->param('POST_'    .$topic_id);
        my $r_post_id  = $iB::CGI->param('R_POST_'  .$topic_id);
        my $choice     = $iB::CGI->param('CHOICE_'  .$topic_id);
        # Did we choose to leave this topic alone?
        ++$count->{'LEFT'} and next if $choice eq 'LEAVE';
        if ($choice eq 'DELETE') {
            ++$count->{'DELETED'};
            $db->delete( TABLE => 'mod_posts',
                         KEY   => $post_id,
                       );
            $db->delete( TABLE => 'forum_topics',
                         ID    => $iB::IN{'f'},
                         KEY   => $topic_id,
                       );
            $db->delete( TABLE  => 'forum_posts',
                         DBID   => 'f'.$iB::IN{'f'},
                         ID     => $topic_id,
                         KEY    => $r_post_id,
                       );
        } elsif ($choice eq 'APPROVE') {
            ++$count->{'APPROVED'};
            my $p_data = $db->select( TABLE => 'mod_posts',
                                      KEY   => $post_id,
                                    );
            my $t_data = $db->select( TABLE => 'forum_topics',
                                      ID    => $iB::IN{'f'},
                                      KEY   => $topic_id,
                                    );
            $db->update( TABLE  => 'forum_topics',
                         ID     => $iB::IN{'f'},
                         KEY    => $topic_id,
                         VALUES => { APPROVED  => 1 },
                       );
            $db->update( TABLE  => 'forum_posts',
                         DBID   => 'f'.$iB::IN{'f'},
                         ID     => $topic_id,
                         KEY    => $r_post_id,
                         VALUES => { QUEUED    => 0 },
                       );
            $db->delete( TABLE => 'mod_posts',
                         KEY   => $post_id,
                       );

            # Update the search records
            $s_log->compile_entry(     DB    => $db,
                                       TOPIC => $t_data,
                                       FORUM => $forum_info,
                                       POST  => $p_data,
                                 );

            # Update the members post count.
            if ($p_data->{'AUTHOR_TYPE'}) {
                my $member = $db->select( TABLE  => 'member_profiles',
                                          KEY    => $p_data->{'AUTHOR'},
                                        );
                ++$member->{'MEMBER_POSTS'};
                $db->update( TABLE  => 'member_profiles',
                             KEY    => $p_data->{'AUTHOR'},
                             VALUES => { MEMBER_POSTS => $member->{'MEMBER_POSTS'} }
                           );
            }
        }
    }

    if ($count->{'APPROVED'}) {
        $obj->_reset_forum( FORUM      => $iB::IN{'f'},
                            ADD_POSTS  => 0,
                            ADD_TOPICS => $count->{'APPROVED'},
                            DB         => $db,
                          );
        $obj->_reset_stats(
                            ADD_POSTS  => 0,
                            ADD_TOPICS => $count->{'APPROVED'},
                          );
    }

    $obj->{html} = ModCPView::startcp();
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::online_menu/e;
    $obj->{html} .= ModCPView::show_topic_results( $count );
    $obj->{html} .= ModCPView::endcp();

}

sub _reset_stats {
    my $obj = shift;
    my %IN  = ( 
                ADD_POSTS  => 0,
                ADD_TOPICS => 0,
                DEL_POSTS  => 0,
                DEL_TOPICS => 0,
                @_,
              );

    $IN{'ADD_POSTS'}  = $IN{'ADD_POSTS'}  - $IN{'DEL_POSTS'};
    $IN{'ADD_TOPICS'} = $IN{'ADD_TOPICS'} - $IN{'DEL_TOPICS'};

    my $stats = {};

    $stats->{'TOTAL_REPLIES'} = '-'.$IN{'DEL_POSTS'};
    $stats->{'TOTAL_TOPICS'}  = '-'.$IN{'DEL_TOPICS'};

    $std->ib_stats( $stats );  
}


sub _reset_forum {
    my $obj = shift;
    my %IN  = ( FORUM      => "",
                DEL_POSTS  => 0,
                DEL_TOPICS => 0,
                ADD_POSTS  => 0,
                ADD_TOPICS => 0,
                DB         => "",
                @_,
              );

    my $db = $IN{'DB'};

    my $s_forum = $db->select( TABLE => 'forum_info',
                               KEY   => $IN{'FORUM'},
                             );

    # Sort out the last post stuff 
    my $old_topic = $db->query( TABLE    => 'forum_topics',
                                ID       => $IN{'FORUM'},
                                WHERE    => "FORUM_ID == $IN{'FORUM'} and APPROVED == 1",
                                RANGE    => "0 to 1",
                                SORT_KEY => "TOPIC_LAST_DATE",
                                SORT_BY  => "Z-A"
                              );

    my ($topics, $posts);

    $topics = $IN{DEL_TOPICS} ? $s_forum->{'FORUM_TOPICS'} - $IN{'DEL_TOPICS'} : $s_forum->{'FORUM_TOPICS'} + $IN{'ADD_TOPICS'};
    $posts  = $IN{DEL_POSTS}  ? $s_forum->{'FORUM_POSTS'}  - $IN{'DEL_POSTS'}  : $s_forum->{'FORUM_POSTS'}  + $IN{'ADD_POSTS'};

    $topics = 0 if $topics < 0;
    $posts  = 0 if $posts  < 0;

    $db->update(  TABLE  => 'forum_info',
                  KEY    => $IN{'FORUM'},
                  VALUES => { L_TOPIC_TITLE       => $old_topic->[0]->{'TOPIC_TITLE'} || '',
                              L_TOPIC_ID          => $old_topic->[0]->{'TOPIC_ID'} || '',
                              FORUM_LAST_POST     => $old_topic->[0]->{'TOPIC_LAST_DATE'},
                              FORUM_LAST_POSTER_N => $old_topic->[0]->{'TOPIC_LASTP_N'} || '',
                              FORUM_LAST_POSTER   => $old_topic->[0]->{'TOPIC_LAST_POSTER'} || '',
                              FORUM_TOPICS        => $topics,
                              FORUM_POSTS         => $posts,
                            },
               );
}





sub _main_splash {
    my ($obj, $db) = @_;

    # Sort out the menu...
    $obj->{html} =~ s/<!--menu goes here-->/&ModCPView::offline_menu/e;

    $obj->{html} .= ModCPView::main_splash();

    # Get the forum/cat combo

    my $cats   = $db->query( TABLE     => 'categories',
                             SORT_KEY  => 'CAT_POS',
                             SORT_BY   => 'A-Z',
                             MATCH     => 'ALL',
                           );

    my $forums = $db->query( TABLE     => 'forum_info',
                             SORT_KEY  => 'FORUM_POSITION',
                             SORT_BY   => 'A-Z',
                             MATCH     => 'ALL'
                           );

    for my $this_cat (@{$cats}) {
        
        # We assume two things:
        #
        # 1) If we are a moderator on this forum, we can read/reply and start threads.
        # 2) No one is stupid enough to make it otherwise.

        my @these_cat_forums = grep { $_->{'CATEGORY'} == $this_cat->{'CAT_ID'} } @{ $forums };
        # which ones do we moderate?
        my @moderated_forums;
        for my $life (@these_cat_forums) {
            if ( ($obj->{type} eq 'all') or (exists $obj->{moderator}->{ $life->{'FORUM_ID'} }) ) {
                push @moderated_forums, $life;
            }
        }

        if (scalar @moderated_forums > 0) {
            $obj->{html} .= ModCPView::render_cat( $this_cat );
            for my $i (@moderated_forums) {
                # Get the number of topics awaiting moderation
                my $need_mod = $db->query( TABLE   => 'forum_topics',
                                           ID      => $i->{'FORUM_ID'},
                                           WHERE   => "APPROVED == 0 and FORUM_ID == '$i->{'FORUM_ID'}'",
                                           COLUMNS => ['TOPIC_ID'],
                                         );
                $i->{'TOPICS_NOT_APPROVED'} = scalar(@{$need_mod}) > 0 ? scalar(@{$need_mod}) : 0;
                $i->{'FORUM_LAST_POST'} = $std->get_date( TIME => $i->{'FORUM_LAST_POST'}, METHOD => 'LONG');
                $obj->{html} .= ModCPView::render_forum( $i );
            }
        }
    }

    $obj->{html} .= ModCPView::end_main_splash();
}








sub Process {
    my ($obj,$db) = @_;

    require "$iB::SKIN->{'DIR'}" . '/ModCPView.pm';
    $obj->SetSession($db);
    my $CodeNo = $iB::IN{'CODE'};
    my %Mode = ( topic_search   => \&topic_search,
                 post_search    => \&post_search,
                 process_topics => \&process_topics,
                 process_posts  => \&process_posts,
                 readpost       => \&read_post,
                 open           => \&open_close_topics,
                 process_open   => \&process_open_close_topics,
                 do_openclose   => \&do_openclose,
                 delete         => \&delete,
                 process_delete => \&process_delete,
                 do_delete      => \&do_delete,
                 prune          => \&prune,
                 process_prune  => \&process_prune,
                 move           => \&move_topics,
                 process_move   => \&process_move,
                 do_move        => \&do_move,
                 
               );

    $Mode{$CodeNo} ? $Mode{$CodeNo}->($obj, $db) : mod_splash($obj, $db);

    unless ($obj->{bypass}) {
        $output->print_ikonboard( DB           => $db,
                                  STD          => $std,
                                  OUTPUT       => $obj->{html},
                                  NAV          => [ qq!<a href='$iB::INFO->{'BOARD_URL'}/ikonboard.$iB::INFO->{'CGI_EXT'}?s=$iB::SESSION;act=ModCP'>$ModCP::lang->{'home'}</a>! ],
                                  TITLE        => "iB::" . "$ModCP::lang->{'title'}"
                                );
    }
} 


#+------------------------------------------------------------------------------------------------------
#+------------------------------------------------------------------------------------------------------
# UNIVERSAL



sub LoadForum {
    my ($obj, $db, $forum) = @_;
    my $return = $db->select( TABLE   => 'forum_info',
                              KEY     => $forum,
                            );
    return $return;
}

#+------------------------------------------------------------------------------------------------------

sub LoadTopic {
    my ($obj, $db, $forum, $topic) = @_;

    my $return = $db->select( TABLE  => 'forum_topics',
                              ID     => $forum,
                              KEY    => $topic,
                            );
    return $return;
}

#+------------------------------------------------------------------------------------------------------

sub SetSession {
    my ($obj, $db) = @_;

    # As our Russian friends might say to non members trying
    # to gain access to our moderators CP: Pisky Ofsky.
    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'moderate_no_permission'
               ) unless $iB::MEMBER->{'MEMBER_ID'};

    # Set the default moderator type to none
    $obj->{type} = 'n';

    # If we're superman...er supermod, then we get "all"
    if ($iB::MEMBER_GROUP->{'IS_SUPMOD'}) {
        $obj->{type} = 'all';
        return;
    }

    # Ok, lets see if this member is a moderator
    my @mods = $db->query( TABLE      => 'forum_moderators',
                           WHERE      => qq!MEMBER_ID eq "$iB::MEMBER->{'MEMBER_ID'}"!
                         );

    # Yes? cool, set the type and return
    if (scalar @mods > 0) {
        $obj->{type} = 'multiple';
        # Build our hash.
        $obj->{moderator} = {};
        for my $i (@mods) {
            $obj->{moderator}->{ $i->{'FORUM_ID'} } = { };
            for my $k (keys %{$i}) {
                next if $k eq 'FORUM_ID';
                $obj->{moderator}->{ $i->{'FORUM_ID'} }->{ $k } = $i->{ $k };
            }
        }
        return;
    }

    # Buh-bye our moderatory challenged friends
    $std->Error( DB      => $db,
                 LEVEL   => 1,
                 MESSAGE =>'moderate_no_permission'
               ) if $obj->{type} eq 'n';


}


1;