#/*
# *  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: Error.pm 363 2007-03-16 15:11:10Z hikarin $
#

package Zeromin::Log::Error;

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

sub new {
    my ( $iClass, $iObject, $key, $ip_int ) = @_;
    my $class = ref $iObject || '';

    return $iClass->SUPER::new( $iObject, $key, $ip_int );
}

sub retrive_by_day {
    my ( $zError, $year, $month, $day ) = @_;
    my $iKernel = $zError->{_kernel};
    my $path    = $iKernel->get_repos_path("${year}/${month}/${day}/error");
    return $zError->_retrive( [$path], $iKernel );
}

sub retrive_by_day_with_page {
    my ( $zError, $year, $month, $day, $item_per_page, $offset ) = @_;
    return _page( $zError->retrive_by_day( $year, $month, $day ),
        $item_per_page, $offset );
}

sub retrive_by_day_in {
    my ( $zError, $year, $month, $day, $bbs, $key ) = @_;
    return $zError->_grep( $zError->retrive_by_day( $year, $month, $day ),
        $bbs, $key );
}

sub retrive_by_day_in_with_page {
    my ( $zError, $year, $month, $day, $bbs, $key, $item_per_page, $offset )
        = @_;
    return _page(
        $zError->retrive_by_day_in( $year, $month, $day, $bbs, $key ),
        $item_per_page, $offset );
}

sub retrive_by_month {
    my ( $zError, $year, $month ) = @_;
    require File::Basename;
    return $zError->all(
        '',
        File::Basename::dirname(
            $zError->{_kernel}->get_repos_path("${year}/${month}/")
        )
    );
}

sub retrive_by_month_with_page {
    my ( $zError, $year, $month, $item_per_page, $offset ) = @_;
    return _page( $zError->retrive_by_month( $year, $month ),
        $item_per_page, $offset );
}

sub retrive_by_month_in {
    my ( $zError, $year, $month, $bbs, $key ) = @_;
    return $zError->_grep( $zError->retrive_by_month( $year, $month ),
        $bbs, $key );
}

sub retrive_by_month_in_with_page {
    my ( $zError, $year, $month, $bbs, $key, $item_per_page, $offset ) = @_;
    return _page( $zError->retrive_by_month_in( $year, $month, $bbs, $key ),
        $item_per_page, $offset );
}

sub all {
    my ( $zError, $regex, $start_path ) = @_;
    my $iKernel = $zError->{_kernel};
    $regex ||= qr{/error\.}xms;

    require File::Basename;
    my $path = $start_path
        || File::Basename::dirname( $iKernel->get_repos_path(0) );
    my $repositories = [];
    require File::Find;
    File::Find::find(
        {   bydepth  => 1,
            no_chdir => 1,
            untaint  => 1,
            wanted   => sub {
                $File::Find::name =~ $regex
                    and push @$repositories, $File::Find::name;
                }
        },
        $path,
    );
    return $zError->_retrive( $repositories, $iKernel );
}

sub all_with_page {
    my ( $zError, $regex, $item_per_page, $offset ) = @_;
    return _page( $zError->all($regex), $item_per_page, $offset );
}

sub all_in {
    my ( $zError, $bbs, $key ) = @_;
    return $zError->_grep( $zError->all(), $bbs, $key );
}

sub all_in_with_page {
    my ( $zError, $bbs, $key, $item_per_page, $offset ) = @_;
    return _page( $zError->all_in( $bbs, $key ), $item_per_page, $offset );
}

sub to_array {
    my ($zError) = @_;
    my $date_table = {};

    $zError->{_rs}->iterate(
        sub {
            my ( $key, $value, $date_table ) = @_;
            if ( $key =~ /\AI:L:E\.(?:.+?\.?:.+?\.\d+\.\d+)\.\w+\z/xms ) {
                $date_table->{$1} = 1;
            }
            return 0;
        },
        $date_table
    );
    return [ keys %$date_table ];
}

sub to_array_with_page {
    my ( $zError, $item_per_page, $offset ) = @_;
    return _page( $zError->to_array(), $item_per_page, $offset );
}

sub _page {
    my ( $entries, $item_per_page, $offset ) = @_;
    require Data::Page;
    my $page = Data::Page->new( scalar @$entries, $item_per_page, $offset );
    return ( [ $page->splice($entries) ], $page );
}

sub _retrive {
    my ( $zError, $repositories, $iKernel ) = @_;
    my $ret  = [];
    my $seen = {};

    for my $iRepos ( map { $iKernel->get_repos_nocache($_) } @$repositories )
    {
        $iRepos->iterate(
            sub {
                my ( $key, $value, $iRepos, $seen, $ret ) = @_;
                if ($key =~ m{
                    \AI:L:E\.(.+?)\.(.+?)\.(\d+?)\.(.+?)\.(\w+)\z
                    }xms
                    )
                {
                    my ( $bbs, $thread_key, $date, $mil, $name )
                        = ( $1, $2, $3, $4, $5 );
                    my $prefix = "I:L:E.${bbs}.${thread_key}.${date}.${mil}";
                    exists $seen->{$prefix} and return 0;
                    $seen->{$prefix} = 1;
                    my $error = $name eq 'error'
                        ? $$value
                        : $iRepos->get("${prefix}.error");
                    my $ip = $name eq 'ip'
                        ? $$value
                        : $iRepos->get("${prefix}.ip");
                    push @$ret,
                        {
                        bbs   => $bbs,
                        key   => $thread_key,
                        ip    => $ip,
                        date  => $date,
                        error => $error,
                        };
                }
                return 0;
            },
            $iRepos,
            $seen,
            $ret,
        );
    }
    @$ret = sort { $b->{date} cmp $a->{date} } @$ret;
    return $ret;
}

sub _grep {
    my ( $zError, $result, $bbs, $key ) = @_;
    my $new_result = [];

    $bbs ||= $zError->{_bbs};
    if ($bbs) {
        @$new_result = grep { $_->{bbs} eq $bbs } @$result;
    }
    if ($key) {
        @$new_result = grep { $_->{key} eq $key } @$result;
    }
    return $new_result;
}

1;
__END__
