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

package Img0ch::Upload::Poll;

use strict;

sub new {
    my ( $iClass, $iBBS, $key ) = @_;
    my $iKernel           = $iBBS->get_kernel();
    my $bbs               = $iBBS->get_name();
    my $repos_upload_poll = '';
    $key
        and $repos_upload_poll
        = Img0ch::Maple::create_repository_subdirs( $key, 'upload_poll',
        $iBBS );

    my $iRepos = '';
    my $prefix = "I:U:P.${bbs}.${key}";
    my $iReposCount
        = $iKernel->get_repos( $iKernel->get_repos_path('upload_pollable') );
    if ($repos_upload_poll) {
        $iRepos = $iKernel->get_repos($repos_upload_poll);
    }

    bless {
        _bbs     => $iBBS,
        _kernel  => $iKernel,
        __now    => time(),
        __prefix => "I:U:P.${bbs}.${key}",
        _rs      => $iRepos,
        _rs_cnt  => $iReposCount,
        __polled => [],
    }, $iClass;
}

sub load {
    my ($iUPoll) = @_;
    my $iRepos = $iUPoll->{_rs};
    $iRepos and $iRepos->load();
    return 1;
}

sub save {
    my ($iUPoll)    = @_;
    my $iRepos      = $iUPoll->{_rs};
    my $iReposCount = $iUPoll->{_rs_cnt};
    my $polled      = $iUPoll->{__polled};
    if ( !@$polled ) {
        $iRepos->save();
        $iReposCount->save();
        return 1;
    }

    my $iKernel = $iUPoll->{_kernel};
    my $prefix  = $iUPoll->{__prefix};
    for my $one (@$polled) {
        my ( $resno, $tag, $ip, $comment, $time, $no_count ) = @$one;
        my $prefix_top   = join '.', $prefix, $resno, $tag;
        my $last_id      = $iRepos->get_int("${prefix_top}._") + 1;
        my $prefix_inner = join '.', $prefix_top, $last_id;
        $iRepos->set_binary( "${prefix_inner}.comment", $comment );
        $iRepos->set( "${prefix_inner}.ip",     $ip );
        $iRepos->set( "${prefix_inner}.polled", $time );
        $iRepos->set( "${prefix_top}._",        $last_id );
        $iRepos->set( "${prefix_top}.count",
            $iRepos->get_int("${prefix_top}.count") + 1 );

        if ( !$no_count ) {
            my $prefix_count = join '.', 'I:U:P.test.0.0', $tag, $ip;
            $iReposCount->set( "${prefix_count}.polled", $time );
            $iReposCount->set( "${prefix_count}.count",
                $iReposCount->get_int("${prefix_count}.count") + 1 );
        }
    }

    @{ $iUPoll->{__polled} } = ();
    $iRepos->save();
    $iReposCount->save();

    return 1;
}

sub add {
    my ( $iUPoll, $resno, $tag, $ip, $comment, $time, $no_count ) = @_;
    $tag =~ /\W+/ and return 0;
    $comment or return 0;
    $iUPoll->is_polled( $resno, $tag, $ip ) and return 0;
    $resno = Img0ch::Kernel::intval($resno);
    $time ||= $iUPoll->{__now};

    push @{ $iUPoll->{__polled} },
        [ $resno, $tag, $ip, $comment, $time, $no_count ];
    return 1;
}

sub get {
    my ( $iUPoll, $resno, $tag ) = @_;
    my $ret = [];
    $tag =~ /\W+/ and return $ret;
    $resno = Img0ch::Kernel::intval($resno);

    my $iRepos  = $iUPoll->{_rs};
    my $prefix  = join '.', $iUPoll->{__prefix}, $resno, $tag;
    my $last_id = $iRepos->get_int("${prefix}._");

    for ( my $i = 1; $i <= $last_id; $i++ ) {
        my $prefix_inner = join '.', $prefix, $i;
        my $comment = $iRepos->get_binary("${prefix_inner}.comment") || next;
        push @$ret,
            {
            comment => $comment,
            ip      => $iRepos->get("${prefix_inner}.ip"),
            polled  => $iRepos->get_int("${prefix_inner}.polled"),
            };
    }
    return $ret;
}

sub count {
    my ( $iUPoll, $resno, $tag ) = @_;
    $tag =~ /\W+/ and return 0;
    $resno = Img0ch::Kernel::intval($resno);
    my $prefix = join '.', $iUPoll->{__prefix}, $resno, $tag;

    return $iUPoll->{_rs}->get_int("${prefix}.count");
}

sub is_polled {
    my ( $iUPoll, $resno, $tag, $ip ) = @_;
    $tag =~ /\W+/ and return 0;
    $resno = Img0ch::Kernel::intval($resno);

    my $iRepos  = $iUPoll->{_rs};
    my $prefix  = join '.', $iUPoll->{__prefix}, $resno, $tag;
    my $last_id = $iRepos->get_int("${prefix}._");

    for ( my $i = 1; $i <= $last_id; $i++ ) {
        my $prefix_inner = join '.', $prefix, $i;
        my $polled_ip = $iRepos->get("${prefix_inner}.ip");
        $polled_ip eq $ip and return 1;
    }
    return 0;
}

sub can_poll {
    my ( $iUPoll, $tag, $ip, $pollable, $time_to_poll, $time ) = @_;
    $pollable     = Img0ch::Kernel::intval($pollable);
    $time_to_poll = Img0ch::Kernel::intval($time_to_poll);
    $time ||= $iUPoll->{__now};

    my $iRepos = $iUPoll->{_rs_cnt};
    my $prefix = join '.', 'I:U:P.test.0.0', $tag, $ip;
    if ( $iRepos->get_int("${prefix}.count") >= $pollable ) {
        if ( $iRepos->get_int("${prefix}.polled") + $time_to_poll < $time ) {
            $iRepos->set( "${prefix}.count",  0 );
            $iRepos->set( "${prefix}.polled", $time );
            $iRepos->save();
            return 1;
        }
        return 0;
    }

    return 1;
}

sub get_pollable_count {
    my ( $iUPoll, $tag, $ip, $pollable ) = @_;
    $pollable = Img0ch::Kernel::intval($pollable);

    my $prefix = join '.', 'I:U:P.test.0.0', $tag, $ip;
    my $ret = $iUPoll->{_rs_cnt}->get_int("${prefix}.count");
    $pollable and $ret = Img0ch::Kernel::intval( $pollable - $ret );

    return $ret;
}

sub remove {
    my ( $iUPoll, $resno, $tag, $ip ) = @_;
    $tag =~ /\W+/ and return 0;
    $resno = Img0ch::Kernel::intval($resno);

    my $iRepos  = $iUPoll->{_rs};
    my $prefix  = join '.', $iUPoll->{__prefix}, $resno, $tag;
    my $last_id = $iRepos->get_int("${prefix}._");

    for ( my $i = 1; $i <= $last_id; $i++ ) {
        my $prefix_inner = join '.', $prefix, $i;
        my $polled_ip = $iRepos->get("${prefix_inner}.ip");
        if ( !$ip or $polled_ip eq $ip ) {
            $iRepos->remove("${prefix_inner}.comment");
            $iRepos->set( "${prefix}.count",
                $iRepos->get_int("${prefix}.count") - 1 );
        }
    }
    return 1;
}

1;
__END__
