#/*
# *  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: UFM.pm 809 2007-06-15 15:02:57Z hikarin $
#

package Img0ch::App::UFM;

use strict;

sub new {
    my ( $iClass, $iKernel, @args ) = @_;
    bless {
        __bbs     => undef,
        __config  => $iKernel->get_config(),
        __kernel  => $iKernel,
        __key     => 0,
        __resno   => 0,
        __request => Img0ch::Request->new(@args),
        __setting => undef,
    }, $iClass;
}

sub run {
    my ($iApp) = @_;
    $iApp->init() or return $iApp->redirect_error('init');

    my $key   = $iApp->{__key};
    my $resno = $iApp->{__resno};
    my ( $result, $iTemplate, $ctype, $body );
    if ( $key and $resno ) {
        ( $result, $iTemplate, $ctype, $body )
            = $iApp->process( $key, $resno );
    }
    else {
        ( $result, $iTemplate, $ctype, $body ) = $iApp->render();
    }

    $result or return $iApp->redirect_error('remove');
    my $iRequest = $iApp->{__request};
    $iRequest->send_http_header( $ctype || 'text/html' );
    $iTemplate ? $iTemplate->flush() : $iRequest->print($body);
    return 1;
}

sub init {
    my ($iApp) = @_;
    my $iRequest = $iApp->{__request};
    $iRequest->init( $iApp->{__config} );

    my $bbs   = $iRequest->bbs();
    my $key   = $iRequest->param_int('key');
    my $resno = $iRequest->param_int('resno');
    if ( my $path_info = $iRequest->path_info() ) {
        my @path = split '/', $path_info;
        ( $path[1] || 'test' ) =~ /([\w\-]+)/xms;
        $bbs = $1;
        ( $path[2] || '00000000' ) =~ /(\d{9,10})/xms;
        $key = $1;
        ( $path[3] || '0' ) =~ /(\d+)/xms;
        $resno = $1;
    }

    require Img0ch::BBS;
    my $iBBS = Img0ch::BBS->new( $iApp->{__kernel}, { bbs => $bbs, } );
    if ( !$iBBS->get_id() ) {
        $iApp->{__error} = 'INVALID_POST';
        return 0;
    }

    require Img0ch::Setting;
    my $iSetting = Img0ch::Setting->new($iBBS);
    $iSetting->load();

    $iApp->{__bbs}     = $iBBS;
    $iApp->{__key}     = $key;
    $iApp->{__resno}   = $resno;
    $iApp->{__setting} = $iSetting;

    return 1;
}

sub process {
    my ( $iApp, $key, $resno ) = @_;
    my $iBBS     = $iApp->{__bbs};
    my $iRequest = $iApp->{__request};

    require Img0ch::Upload;
    my $iUpload = Img0ch::Upload->new( $iBBS, $key );
    my $pass    = $iRequest->param('pass');
    my $process = {};
    if ($pass) {
        my $type = $iRequest->param('type');
        my $js   = {};
        if (    $type eq 'remove'
            and $iUpload->can_remove( $resno, $pass ) )
        {
            $iUpload->remove($resno);
            $iUpload->save();
            $process->{removed} = 1;
            $js->{ok}           = 1;
        }
        elsif ( $type eq 'download'
            and $iUpload->can_download( $resno, $pass ) )
        {
            my $iKernel = $iApp->{__kernel};
            my ($ext)   = @{ $iUpload->get($resno) };
            my $path    = $iUpload->path( $resno, $ext );
            local ( *FH, $! );
            open *FH, "<${path}"    ## no critic
                or $iKernel->throw_io_exception($path);
            binmode *FH;
            my $buffer = do { local $/ = undef; <FH> };
            close *FH or $iKernel->throw_io_exception($path);
            $iRequest->set_header( 'content-disposition',
                'attachment; filename="' . "${resno}.${ext}" . '"' );
            $iRequest->set_header( 'content-length', length($buffer) );
            return ( 1, undef, 'application/octet-stream', \$buffer, );
        }
        elsif ( $type eq 'confirm' ) {
            $js->{remove}   = $iUpload->can_remove( $resno,   $pass );
            $js->{download} = $iUpload->can_download( $resno, $pass );
            $process->{ok}  = 1;
        }
        if ( $iRequest->param('js') ) {
            return ( ( $process->{ok} || $process->{removed} || 0 ),
                undef, 'text/javascript', $iRequest->get_json($js) );
        }
    }

    return $iApp->render( $process, $key, $resno, $pass, );
}

sub render {
    my ( $iApp, $process, $key_param, $resno_param, $pass_param ) = @_;
    my $iBBS     = $iApp->{__bbs};
    my $iRequest = $iApp->{__request};
    $key_param   ||= $iApp->{__key};
    $resno_param ||= $iApp->{__resno};

    require Img0ch::Subject;
    my $iSubject = Img0ch::Subject->new($iBBS);
    my $i        = 1;
    my $stack    = [];
    $iSubject->load();
    for my $key ( @{ $iSubject->to_array() } ) {
        my $subj = $iSubject->get($key);
        push @{$stack},
            {
            res      => $subj->[1],
            key      => $key,
            subject  => $subj->[0],
            count    => $i,
            index    => $i,
            selected => ( $key eq $key_param ),
            };
        $i++;
    }

    require Img0ch::Metadata;
    require Img0ch::Template;
    my $iMeta     = Img0ch::Metadata->new($iBBS);
    my $iTemplate = Img0ch::Template->new(
        $iBBS,
        {   file    => 'ufm',
            request => $iRequest,
            setting => $iApp->{__setting},
        }
    );
    my $removed = $process->{removed};
    $iTemplate->param(
        {   Banner   => $iMeta->main_banner(),
            KEY      => $key_param,
            META     => $iMeta->meta(),
            Password => $pass_param,
            Removed  => $removed,
            Failed   => ( $pass_param and !$removed ),
            Resno    => $resno_param,
            Threads  => $stack,
        }
    );

    return ( 1, $iTemplate, 'text/html', undef, );
}

sub redirect_error {
    my ( $iApp, $reason ) = @_;
    my $iKernel  = $iApp->{__kernel};
    my $iRequest = $iApp->{__request};
    my $key      = $iRequest->key();
    my $ip       = $iRequest->ip_int();

    require Img0ch::Error;
    my $iError = Img0ch::Error->new( $iKernel, $key, $ip );
    my $long = $iError->get( $iApp->{__error} || 'INVALID_POST' );
    $iError->record();

    if ( $iRequest->param('js') ) {
        $iRequest->send_http_header( 'text/javascript', 'UTF-8' );
        $iRequest->print(
            $iRequest->get_json( { ok => 0, error => $reason } ) );
    }
    else {
        require Img0ch::Template;
        my $iTemplate = Img0ch::Template->new(
            ( $iApp->{__bbs} || $iKernel ),
            {   file    => ('error'),
                request => $iRequest,
                setting => $iApp->{__setting},
            }
        );
        $iTemplate->param(
            {   Banner       => '',
                Flag         => 0,
                LongErrorStr => $long,
            }
        );
        my $iConfig = $iApp->{__config};
        my $charset = $iConfig->get('DefaultCharset');
        $iRequest->send_http_header( 'text/html', $charset );
        $iTemplate->flush();
    }
}

1;
__END__
