#/*
# *  Copyright 2007-2010 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: Pool.pm 1901 2009-12-31 02:40:20Z hikarin $
#

package Zeromin::Pool;

use strict;
use Img0ch::Pool::Subject qw();
use Img0ch::Pool::Thread qw();
use Zeromin::Subject qw();
use Zeromin::Thread qw();
use Zeromin::Upload qw();

sub new {
    my ( $zClass, $iObject, $key ) = @_;
    my $class = ref $iObject || '';
    my ( $zPool, $iBBS );

    if ( $class eq 'Zeromin::Thread' or $class eq 'Img0ch::Thread' ) {
        $key ||= $iObject->get_key();
        $iBBS  = $iObject->get_bbs();
        $zPool = bless {
            __bbs => $iBBS,
            __key => $key,
        }, $zClass;
        $iObject->load();
        $zPool->{__thread} = $iObject;
    }
    elsif ( $class eq 'Img0ch::BBS' or $class eq 'Zeromin::BBS' ) {
        $iBBS = $iObject;
        $key ||= 0;
        $zPool = bless {
            __bbs => $iBBS,
            __key => $key
        }, $zClass;
        my $zThread = Zeromin::Thread->new( $iBBS, $key );
        $zThread->load();
        $zPool->{__thread} = $zThread;
    }
    else {
        Img0ch::Kernel->throw_exception(
            'Zeromin::Thread or Img0ch::BBS not given');
    }

    my $zSubject = Zeromin::Subject->new($iBBS);
    $zSubject->load();
    $zSubject->include_special_threads();
    $zPool->{__pool_subject} = Img0ch::Pool::Subject->new($iBBS);
    $zPool->{__pool_thread}  = Img0ch::Pool::Thread->new( $iBBS, $key );
    $zPool->{__subject}      = $zSubject;
    $zPool->{__upload}       = Zeromin::Upload->new( $iBBS, $key );

    return $zPool;
}

sub load {
    my ($zPool) = @_;
    $zPool->{__pool_subject}->load();
    $zPool->{__pool_thread}->load();
    $zPool->{__thread}->load();
    $zPool->{__upload}->load();
    return 1;
}

sub get {
    my ( $zPool, $key, $resno ) = @_;
    if ($resno) {
        return $zPool->{__pool_thread}->get($resno);
    }
    else {
        return $zPool->{__pool_subject}->get($key);
    }
}

sub get_utf8 {
    my ( $zPool, $key, $resno ) = @_;
    if ($resno) {
        return $zPool->{__pool_thread}->get_utf8($resno);
    }
    else {
        return $zPool->{__pool_subject}->get_utf8($key);
    }
}

sub get_pool_subject_instance { $_[0]->{__pool_subject} }

sub get_pool_thread_instance { $_[0]->{__pool_thread} }

sub get_thread_instance { $_[0]->{__thread} }

sub get_upload_instance { $_[0]->{__upload} }

sub set_key {
    my ( $zPool, $key ) = @_;
    $zPool->{__key} = $key;
    $zPool->{__thread}->set_key($key);
    $zPool->{__pool_thread}->set_key($key);
    $zPool->{__upload}->set_key($key);
    return;
}

sub create {
    my ($zPool) = @_;
    my $zPThread = $zPool->{__pool_thread};
    $zPThread->count() and return 0;

    my $zThread   = $zPool->{__thread};
    my $zPSubject = $zPool->{__pool_subject};
    my $count     = $zThread->count();
    my $subject   = $zThread->get_subject();
    $zPThread->set( [ @{ $zThread->get(1) }, $subject ], 1 );
    for ( my $i = 2; $i <= $count; $i++ ) {
        $zPThread->set( $zThread->get($i), $i );
    }

    my $key = $zPool->{__key};
    $zPThread->save();
    $zPSubject->set( $key, $count, $subject );
    $zPSubject->save();
    $zPool->{__thread}->remove();
    $zPool->{__upload}->freeze();
    $zPool->_plugin('zeromin.pool.thread');

    return 1;
}

sub restore {
    my ($zPool) = @_;
    my $zPThread = $zPool->{__pool_thread};
    $zPThread->count() or return 0;

    my $zThread = $zPool->{__thread};
    my $count   = $zPThread->count();
    $zThread->set( [ @{ $zPThread->get(1) }, $zPThread->get_subject() ], 1 );
    for ( my $i = 2; $i <= $count; $i++ ) {
        $zThread->set( $zPThread->get($i), $i );
    }
    $zThread->save();

    my $zSubject = $zPool->{__subject};
    $zSubject->load();
    $zSubject->age( $zPool->{__key}, $count, $zPThread->subject() );
    $zSubject->save();
    $zPool->remove();
    $zPool->{__upload}->release();
    $zPool->_plugin('zeromin.restore.thread');

    return 1;
}

sub remove {
    my ($zPool) = @_;
    my $zPThread = $zPool->{__pool_thread};
    $zPThread->count() or return 0;

    my $zPSubject = $zPool->{__pool_subject};
    if ( $zPSubject->remove( $zPool->{__key} ) ) {
        $zPSubject->save();
        my $ret = $zPThread->remove();
        $zPool->{__upload}->remove();
        $zPool->_plugin('zeromin.remove.pool');
        return $ret;
    }
    else {
        return 0;
    }
}

sub get_subject { shift->{__pool_subject}->get_subject(@_) }

sub to_array { $_[0]->{__pool_subject}->to_array() }

sub to_array_with_page {
    my ( $zPool, $item_per_page, $offset ) = @_;

    defined $Data::Page::VERSION or require Data::Page;
    my $entries = $zPool->to_array();
    my $page = Data::Page->new( scalar @$entries, $item_per_page, $offset );
    return ( [ $page->splice($entries) ], $page );
}

sub _plugin {
    my ( $zPool, $at ) = @_;
    require Zeromin::Plugin;
    my $iBBS    = $zPool->{__bbs};
    my $key     = $zPool->{__key};
    my $zPlugin = Zeromin::Plugin->new($iBBS);
    $zPlugin->do( $at, $zPool, [ $iBBS, $key ] );
    return;
}

1;
__END__
