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

package Img0ch::App::Imager;

use strict;
use IO::String qw();
use Img0ch::BBS qw();

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

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

    my $key   = $iApp->{__key};
    my $resno = $iApp->{__resno};
    my $ret   = [];
    if ( $key and $resno ) {
        $iApp->process( $key, $resno, $ret )
            or return $iApp->redirect_error('init');
    }
    else {
        return $iApp->redirect_error('init');
    }

    my $iRequest = $iApp->{__request};
    my ( $ctype, $body ) = @$ret;
    $iRequest->send_http_header( $ctype || 'text/html' );
    $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;
    }

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

    my $iThread = $iBBS->get_thread_instance($key);
    if ( !$iThread->count() ) {
        $iApp->{__error} = 'INVALID_POST';
        return 0;
    }

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

    return 1;
}

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

    my $iUpload   = $iBBS->get_upload_instance($key);
    my $info      = $iUpload->get($resno);
    my $extension = $info->[0];
    if ($extension
        and (  $iUpload->have_download_password($resno)
            or $iUpload->is_freezed($resno) )
        )
    {
        $iApp->{__error} = 'ACCESS_TO_FREEZED_FILE';
        return 0;
    }

    my $screen_size = [];
    if ( !$iApp->get_screen_size( $screen_size, $iRequest ) ) {
        $iApp->{__error} = 'ACCESS_FROM_NOT_MOBILE';
        %{ $iApp->{__error_args} } = (
            TYPE => $iRequest->agent(),
            UA   => $iRequest->get_header('user-agent'),
        );
        return 0;
    }

    if (    my $width = $info->[1]
        and my $height = $info->[2] )
    {

        my $path = $iUpload->path( $resno, $extension );
        my ( $w, $h ) = $iUpload->scale( $width, $height, @$screen_size );

        my $ios = IO::String->new();
        if ( $width > $w or $height > $h ) {
            require Img0ch::Upload::Thumbnail;
            if (Img0ch::Upload::Thumbnail->create(
                    $iApp->{__kernel},
                    {   ext    => $extension,
                        fh     => $ios,
                        height => $h,
                        path   => $path,
                        width  => $w,
                    }
                )
                )
            {
                $ret->[1] = $ios->string_ref();
            }
        }
        else {
            my $iKernel = $iApp->{__kernel};
            my $fh      = $iKernel->get_read_file_handle($path);
            while ( read( $fh, my $buffer, 8192 ) ) {
                $ios->print($buffer);
            }
            close $fh or $iKernel->throw_io_exception($path);
            $ret->[1] = $ios->string_ref();
        }

        $extension eq 'jpg' and $extension = 'jpeg';
        $ret->[0] = 'image/' . $extension;
        return 1;
    }
    return 0;
}

sub get_screen_size {
    my ( $iApp, $screen_size, $iRequest ) = @_;
    my $iConfig = $iApp->{__config};
    $iRequest ||= $iApp->{__request};

    my $type2carrer = [ undef, 'docomo', 'softbank', 'au' ];
    my $type = $iRequest->agent();

    if ( defined $type2carrer->[$type] ) {
        my $path = $iConfig->get('SystemPath') . '/screen-mobile-device.ini';
        my $config  = Config::Tiny->read($path);
        my $ua      = lc $iRequest->get_header('user-agent');
        my %devices = %{ $config->{ $type2carrer->[$type] } };
        while ( my ( $name, $info ) = each %devices ) {
            if ( index( $ua, lc($name) ) >= 0 ) {
                my ( $width, $height ) = split ',', $info, 2;
                @$screen_size = (
                    Img0ch::Kernel::intval($width),
                    Img0ch::Kernel::intval($height),
                );
                return 1;
            }
        }
    }
    elsif ( my $pixels = $iRequest->get_header('ua-pixels') ) {
        my ( $width, $height ) = split 'x', $pixels;
        @$screen_size = (
            Img0ch::Kernel::intval($width),
            Img0ch::Kernel::intval($height),
        );
        return 1;
    }
    return 0;
}

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

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

    while ( my ( $subs, $value ) = each %{ $iApp->{__error_args} } ) {
        $long =~ s/{!$subs!}/$value/gxms;
    }

    if ( $iRequest->param('js') ) {
        $iRequest->send_http_header( 'text/javascript', 'UTF-8' );
        $iRequest->print(
            $iRequest->get_json( { ok => 0, error => $reason } ) );
    }
    else {
        defined &{'Img0ch::Template::new'} or require Img0ch::Template;
        my $iBBS = $iApp->{__bbs};
        my $iSetting;
        $iBBS and $iBBS->get_setting_instance();
        my $iTemplate = Img0ch::Template->new(
            ( $iBBS || $iKernel ),
            {   file    => ('error'),
                request => $iRequest,
                setting => $iSetting,
            }
        );
        $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__
