#/*
# *  Copyright 2007 hkrn <hikarin@users.sourceforge.jp>
# *
# *  Licensed under the Apache License, Version 2.0 (the "License");
# *  you may not use this file except in compliance with the License.
# *  You may obtain a copy of the License at
# *
# *      http://www.apache.org/licenses/LICENSE-2.0
# *
# *  Unless required by applicable law or agreed to in writing, software
# *  distributed under the License is distributed on an "AS IS" BASIS,
# *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# *  See the License for the specific language governing permissions and
# *  limitations under the License.
# */
#
# $Id: thread.pm 610 2007-05-09 14:49:15Z hikarin $
#

package Zeromin::App::thread;

use strict;

sub load {
    my ($zApp) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    my $key   = $zApp->key()  || return { code => 1 };
    my $encoding = $zApp->kernel()->get_encoding(1);
    my $iRequest = $zApp->request();

    require Zeromin::Thread;
    require Unicode::Japanese;
    my $zThread = Zeromin::Thread->new( $iBBS, $key );
    my $unijp   = Unicode::Japanese->new();
    my $count   = $zThread->load();

    if ( my $resno = $iRequest->param_int('resno') ) {
        my $ret  = $zThread->get($resno);
        my $id   = $ret->[3];
        my $date = $id ? join( ' ', $ret->[2], $id ) : $ret->[2];
        return {
            code    => 0,
            content => {
                name    => $unijp->set( $ret->[0], $encoding )->get(),
                mail    => $unijp->set( $ret->[1], $encoding )->get(),
                date    => $unijp->set( $date,     $encoding )->get(),
                message => $unijp->set( $ret->[4], $encoding )->get(),
            },
        };
    }
    else {
        require Img0ch::Log;
        my $iLog = Img0ch::Log->new( $iBBS, $key );
        my $ret = [];
        for ( my $i = 1; $i <= $count; $i++ ) {
            my $res  = $zThread->get($i);
            my $log  = $iLog->get($i);
            my $id   = $res->[3];
            my $date = $id ? join( ' ', $res->[2], $id ) : $res->[2];
            push @{$ret},
                {
                resno   => $i,
                name    => $unijp->set( $res->[0], $encoding )->get(),
                mail    => $unijp->set( $res->[1], $encoding )->get(),
                date    => $unijp->set( $date, $encoding )->get(),
                message => $unijp->set( $res->[4], $encoding )->get(),
                ip      => join( '.', unpack( 'C*', $log->[1] ) ),
                serial  => $log->[2],
                agent   => $log->[3],
                stamp   => $log->[0],
                };
        }
        if ( my $offset = $iRequest->param_int('offset') ) {
            my $item = $iRequest->param_int('item') || 10;
            $ret = $zApp->paging_from_array( $ret, $offset, $item );
        }
        return {
            code    => 0,
            content => $ret,
            subject => $unijp->set( $zThread->subject(), $encoding )->get(),
        };
    }
}

sub save {
    my ($zApp) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    my $key   = $zApp->key()  || return { code => 1 };
    my $dir      = $iBBS->get_name();
    my $encoding = $zApp->kernel()->get_encoding(1);
    my $iRequest = $zApp->request();
    my $resno    = $iRequest->param_int('resno') || return { code => 1 };
    $zUser->can_edit_res() or return { code => 1 };

    require Zeromin::Thread;
    require Unicode::Japanese;
    my $zThread = Zeromin::Thread->new( $iBBS, $key );
    my $unijp   = Unicode::Japanese->new();
    my $count   = $zThread->load();
    my $from
        = $zApp->kernel()->get_config()->get('EnableEditName')
        ? $unijp->set( $iRequest->param( 'FROM', 1 ), 'utf8' )->$encoding
        : undef;
    defined $from and $from =~ tr/\r\t\n//d;
    my $mail
        = $unijp->set( $iRequest->param( 'mail', 1 ), 'utf8' )->$encoding;
    $mail =~ tr/\r\t\n//d;
    my $message
        = $unijp->set( $iRequest->param( 'MESSAGE', 1 ), 'utf8' )->$encoding;
    $message =~ tr/\r\t//d;
    $message =~ s/\n/<br>/g;
    $zThread->load();

    if ( $zThread->edit( $resno, [ $from, $mail, undef, undef, $message ] ) )
    {
        $zApp->logger(
            1,
            'EDITED RES: %s/dat/%s.dat at %d',
            [ $dir, $key, $resno ]
        );
        return { code => 0 };
    }
    else {
        $zApp->logger(
            0,
            'TRIED EDITTING INEXISTING RES: %s/dat/%s.dat at %d',
            [ $dir, $key, $resno ]
        );
        return { code => 2 };
    }
}

sub remove {
    my ($zApp) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    my $dir      = $iBBS->get_name();
    my $iRequest = $zApp->request();
    my $status   = {};

    if ( my $resno = $iRequest->param('resno') ) {
        my $is_erase     = 0;
        my $is_file_only = 0;
        my $type;
        if ( $iRequest->param('is_erase') ) {
            $zUser->can_remove_res() or return { code => 1 };
            $type     = 'ERASE';
            $is_erase = 1;
        }
        elsif ( $iRequest->param('is_file_only') ) {
            $zUser->can_abone_res() or return { code => 1 };
            $type         = 'FILE ONLY';
            $is_file_only = 1;
        }
        else {
            $zUser->can_abone_res() or return { code => 1 };
            $type = 'ABONE';
        }
        require Zeromin::Thread;
        my $key     = $zApp->key();
        my $zThread = Zeromin::Thread->new( $iBBS, $key );
        my $remove  = [ my @ret = $iRequest->param('resno') ];
        $zThread->load();
        $zThread->remove(
            $remove,
            {   is_erase     => $is_erase,
                is_file_only => $is_file_only,
            }
        );
        $zApp->logger(
            1,
            'REMOVED RES WITH %s: %s at %s/dat/%s.dat',
            [ $type, $resno, $dir, $key ]
        );
        map { $status->{$_} = 1 } @$remove;
    }
    else {
        $zUser->can_remove_thread or return { code => 1 };
        require Zeromin::Thread;
        my $zThread = Zeromin::Thread->new( $iBBS, $zApp->key() );
        my @keys = $iRequest->param('key');
        for my $key (@keys) {
            $zThread->set_key($key);
            $zThread->load();
            my $subject = $zThread->subject();
            my $count   = $zThread->count();
            $zThread->remove();
            $zApp->logger(
                1,
                'REMOVED THREAD: %s/dat/%s.dat - %s(%s)',
                [ $dir, $key, $subject, $count ]
            );
            $status->{$key} = 1;
        }
    }

    return { code => 0, removed => $status };
}

sub doImport {
    my ($zApp) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    $zUser->can_recreate_subject() or return { code => 1 };

    my $iRequest = $zApp->request();
    $iRequest->is_uploadable('file') or return { code => 2 };

    require Zeromin::Thread;
    my $zThread = Zeromin::Thread->new($iBBS);
    my $param   = $iRequest->filename('file');
    my $ret     = $zThread->import_from( $iRequest->tempfile(), $param );

    return { code => ( $ret ? 0 : 3 ) };
}

sub doExport {
    my ($zApp) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    $zUser->can_recreate_subject() or return { code => 1 };

    my $iRequest = $zApp->request();

    return { code => 0 };
}

sub pool {
    require Zeromin::App::pool;
    Zeromin::App::pool::create(shift);
}

sub stop {
    _do_task( shift, 'stop', 'can_stop_thread', 'STOPPED', 'TRIED STOPPING',
    );
}

sub restart {
    _do_task( shift, 'restart', 'can_restart_thread', 'RESTARTED',
        'TRIED RESTARTING',
    );
}

sub _do_task {
    my ( $zApp, $method, $privilege, $success, $failed ) = @_;
    my $zUser = $zApp->user() || return { code => 1 };
    my $iBBS  = $zApp->bbs()  || return { code => 1 };
    my $iRequest = $zApp->request();
    my $status = { code => 0 };

    $zUser->$privilege or return { code => 1 };
    require Zeromin::Thread;
    my $zThread = Zeromin::Thread->new( $iBBS, 0 );
    my $dir     = $iBBS->get_name();
    my @keys    = $iRequest->param('key');

    for my $key (@keys) {
        $zThread->set_key($key);
        $zThread->load();
        my $subject = $zThread->subject();
        my $count   = $zThread->count();
        if ( $zThread->$method($key) ) {
            $zApp->logger(
                1,
                "$success: %s/dat/%s.dat - %s(%s)",
                [ $dir, $key, $subject, $count ]
            );
            $status->{$key} = 1;
        }
        else {
            $zApp->logger(
                0,
                "$failed: %s/dat/%s.dat - %s(%s)",
                [ $dir, $key, $subject, $count ]
            );
            $status->{$key} = 0;
        }
    }

    return $status;
}

1;
__END__
