#/*
# *  Copyright 2007-2009 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 1826 2009-04-08 15:23:25Z hikarin $
#

package Img0ch::Pool::Thread;

use strict;
use base qw(Img0ch::Thread);

sub new {
    my ( $iClass, $iBBS, $key ) = @_;
    my $iKernel = $iBBS->get_kernel();

    my $pool_thread_dir
        = Img0ch::Maple::create_repository_subdirs( $key, $key, $iBBS );
    $pool_thread_dir =~ s{/$key.\w+\z}{}xms;
    my $pool_thread_dir2
        = Img0ch::Maple::create_repository_subdirs( $key, $key, $iKernel );
    $pool_thread_dir2 =~ s{/$key.\w+\z}{}xms;
    my $pool_thread_dir3 = $pool_thread_dir2;
    $pool_thread_dir3 =~ s{/\d+\z}{}xms;

    bless {
        _bbs      => $iBBS->get_name(),
        _count    => 0,
        _encoding => $iKernel->get_encoding(1),
        _i0_bbs   => $iBBS,
        _kernel   => $iKernel,
        _key      => $key,
        _line     => [],
        __path    => $pool_thread_dir,
        __path1   => $pool_thread_dir,
        __path2   => $pool_thread_dir2,
        __path3   => $pool_thread_dir3,
    }, $iClass;
}

sub load {
    my ( $iPool, $path ) = @_;
    my $changed = 0;

    if ( !$path and !-e $iPool->path() ) {
        $iPool->{__path} = $iPool->{__path2};
        $path = $iPool->path();
        if ( !-e $path ) {
            $iPool->{__path} = $iPool->{__path3};
            $path = $iPool->path();
        }
        $changed = 1;
    }

    my $ret = $iPool->SUPER::load($path);
    $changed and $iPool->{__path} = $iPool->{__path1};

    return $ret;
}

sub get_utf8 {
    my ( $iPool, $resno ) = @_;
    my $iKernel = $iPool->{_kernel};
    my $result  = $iPool->get($resno);
    my $ret     = [];

    for my $column (@$result) {
        push @$ret,
            $iKernel->get_encoded_str( $column, 'utf8', $iPool->{_encoding} );
    }

    return $ret;
}

sub set {
    my ( $iPool, $element, $pos ) = @_;
    my $subject = $element->[5] || '';
    my $id = $element->[3] ? " $element->[3]" : '';
    my $line = "$element->[0]<>$element->[1]<>$element->[2]"
        . "$id<>$element->[4]<>${subject}\n";

    if ($pos) {
        splice @{ $iPool->{_line} }, ( $pos - 1 ), 1, ($line);
    }
    else {
        push @{ $iPool->{_line} }, $line;
    }
    return;
}

sub set_key {
    my ( $iPool, $key ) = @_;

    my $pool_thread_dir
        = Img0ch::Maple::create_repository_subdirs( $key, $key,
        $iPool->{_i0_bbs} );
    $pool_thread_dir =~ s{/$key.\w+\z}{}xms;
    my $pool_thread_dir2
        = Img0ch::Maple::create_repository_subdirs( $key, $key,
        $iPool->{_kernel} );
    $pool_thread_dir2 =~ s{/$key.\w+\z}{}xms;
    my $pool_thread_dir3 = $pool_thread_dir2;
    $pool_thread_dir3 =~ s{/\d+\z}{}xms;

    $iPool->{_key}    = $key;
    $iPool->{__path}  = $pool_thread_dir;
    $iPool->{__path1} = $pool_thread_dir;
    $iPool->{__path2} = $pool_thread_dir2;
    $iPool->{__path3} = $pool_thread_dir3;

    $iPool->SUPER::set_key($key);
}

sub remove {
    my ($iPool) = @_;
    my $changed = 0;
    my $path    = $iPool->path();

    if ( !-e $path ) {
        $iPool->{__path} = $iPool->{__path2};
        $path = $iPool->path();
        if ( !-e $path ) {
            $iPool->{__path} = $iPool->{__path3};
            $path = $iPool->path();
        }
        $changed = 1;
    }

    if ( -w $path ) {
        my $iKernel = $iPool->{_kernel};
        unlink $path or $iKernel->throw_io_exception($path);
        $iPool->{_count} = 0;
        $changed and $iPool->{__path} = $iPool->{__path1};
        return 1;
    }
    else {
        $changed and $iPool->{__path} = $iPool->{__path1};
        return 0;
    }
}

1;
__END__

=head1 NAME

Img0ch::Pool::Thread - プールスレッドを管理するクラス

=head1 SYNOPSYS

  use Img0ch::Pool::Thread

  my $iPool = Img0ch::Pool::Thread->new($iBBS, $key);
  $iPool->load();

  my ($name, $mail, $date, $id, $comment) = @{ $iPool->get(1) };
  my $subject = $iPool->get_subject();

  $iPool->set([$name, $mail, $date, $id, $comment]);
  $iPool->save();

=head2 new

=over 4

=item Arguments

$iBBS(Img0ch::BBS), $key

=item Return Value

$iPool (Img0ch::Pool::Thread itself)

=back

I<Img0ch::Pool::Thread>のオブジェクトを作成します。

=head2 load

=over 4

=item Arguments

none

=item Return Value

$count

=back

スレッドを読み込みます。返り値はレス数を返します。

=head2 save

=over 4

=item Arguments

$path?

=item Return Value

1(saved) or 0

=back

I<set()>の内容をスレッドに追記し、保存します。
I<set()>が一度も呼び出されていなければレス数を更新し、0を返します。

=head2 get

=over 4

=item Arguments

$resno

=item Return Value

$array_reference

=back

指定されたレスの内容を配列のリファレンスとして取り出します。
名前、メール欄、時刻、ID、本文の順番に値が返されます。

=head2 get_subject

=over 4

=item Arguments

none

=item Return Value

$subject

=back

現在のプールスレッド名を返します。

=head2 set

=over 4

=item Arguments

$arrray_reference, $pos?

=item Return Value

none

=back

追記する内容をオブジェクト内部に一時的に保存します。
I<$pos>が指定されている場合はI<$pos>のレス番号に内容が保存されます。

=head2 set_key

=over 4

=item Arguments

$key

=item Return Value

none

=back

オブジェクト内部に保存されているスレッドキーを変更します。
別のスレッドの内容を読み込む場合に利用します。

=head2 count

=over 4

=item Arguments

none

=item Return Value

$count

=back

現在のスレッドのレス数を返します。

=head2 search

=over 4

=item Arguments

$regex, $pos

=item Return Value

$hash_reference_of_result

=back

現在のプールスレッドの一覧から$regexの正規表現で検索します。
$posを指定することで検索単位を変更することが出来ます。
この場合スレッドの一覧では無くプールスレッドの中身を検索します。
デフォルトで5が指定されます。

$posで指定できる値と検索単位は以下の通りです。

=over 4

=item 1(FROM)

名前欄から検索します。

=item 2(mail)

メール欄から検索します。

=item 3(date)

時刻から検索します。

=item 4(id)

IDから検索します。

=item 5(message)

本文から検索します。

=back

=head2 remove

=over 4

=item Arguments

none

=item Return Value

1 or 0

=back

現在のスレッドを削除します。スレッドが存在しない場合は0を返します。
スレッドの削除が出来ない場合は例外を発行します。

=head1 AUTHOR

hkrn E<lt>hikarin@users.sourceforge.jpE<gt>

=cut
