#/*
# *  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 Img0ch::Error;

use strict;

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

    if ( $class eq 'Img0ch::BBS' ) {
        $iKernel = $iObject->get_kernel();
        $bbs     = $iObject->get_name() || 'test';
        $common  = $iObject->get_common_repos();
    }
    elsif ( $class eq 'Img0ch::Kernel' or $class eq 'Img0ch::Maple' ) {
        $iKernel = $iObject;
        $bbs     = 'test';
        $common  = $iKernel->get_repos( $iKernel->get_repos_path('common') );
    }
    else {
        Img0ch::Kernel->throw_exception(
            'Img0ch::BBS or Img0ch::Maple(Img0ch::Kernel) not given');
    }

    my $date = time();
    my ( undef, undef, undef, $day, $month, $year ) = localtime($date);
    $year  += 1900;
    $month += 1;

    my $path       = join '/', $year, $month, $day, 'error';
    my $repos_path = $iKernel->get_repos_path($path);
    my $repos_dir  = $repos_path;
    $repos_dir =~ s{/error.\w+\z}{}xms;
    if ( !-d $repos_dir ) {
        require File::Path;
        File::Path::mkpath($repos_dir)
            or $iKernel->throw_io_exception($repos_dir);
    }

    my $iRepos = $iKernel->get_repos_nocache($repos_path);
    bless {
        _bbs    => $bbs,
        __cache => '',
        __date  => $date,
        __error => $common,
        __ip    => $ip_int,
        _kernel => $iKernel,
        __key   => ( $key || '0' ),
        _rs     => $iRepos,
    }, $iClass;
}

sub load { $_[0]->{_rs}->load(); return 1 }

sub get {
    my ( $iError, $key ) = @_;
    my $cache = $iError->{__cache} || '';
    $cache and return $cache;

    my $content = $iError->{__error}->get("I:E.${key}");
    if ($content) {
        $iError->{__cache} = $key;
        return $content;
    }
    else {
        my $iKernel = $iError->{_kernel};
        my $iConfig = $iKernel->get_config();
        my $path    = $iConfig->get('SystemPath') . '/error.txt';
        local ( $!, *FH );
        open *FH, "<${path}"    ## no critic
            or $iKernel->throw_io_exception($path);
        while ( my $line = <FH> ) {
            chomp $line;
            my ( $errid, $errmsg ) = ( split '<>', $line )[ 0, 2 ];
            if ( $key eq $errid ) {
                close *FH or $iKernel->throw_io_exception($path);
                $iError->{__cache} = $key;
                my $iRepos = $iError->{__error};
                $iRepos->set( "I:E.${errid}", $errmsg );
                $iRepos->save();
                return $errmsg;
            }
        }
        close *FH or $iKernel->throw_io_exception($path);
    }
    return '';
}

sub record {
    my ($iError) = @_;
    if (    my $cache = $iError->{__cache}
        and my $ip_int = $iError->{__ip} )
    {
        my $iRepos = $iError->{_rs};
        my $bbs    = $iError->{_bbs};
        my $key    = $iError->{__key};
        my $date   = $iError->{__date};
        my $mil    = int( rand(99999) );
        my $prefix = "I:L:E.${bbs}.${key}.${date}.${mil}";
        $iRepos->set( "${prefix}.error", $cache );
        $iRepos->set( "${prefix}.ip", join( '.', unpack( 'C*', $ip_int ) ) );
        $iRepos->save();
        return 1;
    }
    0;
}

1;
__END__

=head1 NAME

Img0ch::Error - エラー処理を行うクラス

=head1 SYNOPSYS

  use Img0ch::Error

  my $iError = Img0ch::Error->new($iBBS, $key, $ip);

  # INVALID_POSTのメッセージを取り出す
  my $errstr = $iError->get('INVALID_POST');
  # エラー記録を行う
  my $true_or_false = $iError->record();

=head1 DESCRIPTION

1つのエラー処理を1つのオブジェクトとするクラスです。

=head2 new

=over 4

=item Arguments

$iBBS(Img0ch::BBS) or $iKernel(Img0ch::Kernel), $key?, $ip?

=item Return Value

$iError (Img0ch::Error itself)

=back

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

=head2 load

=over 4

=item Arguments

none

=item Return Value

1

=back

レポジトリを読み込みます。

=head2 get

=over 4

=item Arguments

$key

=item Return Value

$message

=back

I<$key>に対応付けるエラーメッセージを返します。
存在しない場合はナルストリングを返します。

=head2 record

=over 4

=item Arguments

none

=item Return Value

1(succeeded) or 0

=back

get()で呼び出された情報からエラー記録を行います。
get()を呼び出されていない場合は0を返します。

=head1 AUTHOR

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

=cut
