#/*
# *  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: Thumbnail.pm 615 2007-05-10 14:22:45Z hikarin $
#

package Img0ch::Plugin::Upload::Thumbnail;

use strict;

sub new {
    my ( $iClass, $iBBS, $key, $called ) = @_;
    $called eq 'iterator' or return;

    require Img0ch::Setting;
    require Img0ch::Upload;
    my $iSetting = Img0ch::Setting->new($iBBS);
    my $iUpload = Img0ch::Upload->new( $iBBS, $key );

    bless {
        __kernel  => $iBBS->get_kernel(),
        __setting => $iSetting,
        __upload  => $iUpload,
    }, $iClass;
}

sub create {
    my ($iApp) = @_;
    my $iUpload = $iApp->upload();
    -r $iUpload->get_uploaded_file_path() or return 0;

    my $iKernel  = $iApp->kernel();
    my $iSetting = $iApp->setting();
    _process( $iKernel, $iSetting, $iUpload );
    return 1;
}

*batch = \&repair;
sub repair {
    my ( $iObject, $key ) = @_;
    my $iKernel  = $iObject->{__kernel};
    my $iSetting = $iObject->{__setting};
    my $iUpload  = $iObject->{__upload};

    $iUpload->set_key($key);
    for my $file_path ( @{ $iUpload->traverse() } ) {
        $file_path =~ m{/\d+\.(?:gif|jpg|png)\z}xms or next;
        _process( $iKernel, $iSetting, $iUpload, $file_path );
    }
    return 1;
}

sub _process {
    my ( $iKernel, $iSetting, $iUpload, $path ) = @_;
    my $iConfig    = $iKernel->get_config();
    my $handler    = $iConfig->get('ImageHandler') || 'repng2jpeg';
    my $max_width  = $iSetting->get_int('BBS_IMG_THUMBNAIL_X');
    my $max_height = $iSetting->get_int('BBS_IMG_THUMBNAIL_X');

    $path ||= $iUpload->get_uploaded_file_path();
    my $dest = $path;

    my ( $resno, $ext ) = $path =~ m{/(\d+)\.(\w+)\z}xms;
    my ( $width, $height ) = $iUpload->get_dimensions($path);
    my ( $scaled_width, $scaled_height )
        = $iUpload->scale( $width, $height, $max_width, $max_height );
    $dest =~ s{/(\d+\..+)\z}{/t$1}xms;

    if ( $handler eq 'repng2jpeg' ) {
        $ext ne 'jpg' and $ext ne 'gif' and $ext ne 'png' and return 1;
        my $binary = $^O eq 'MSWin32' ? 'repng2jpeg.exe' : 'repng2jpeg';
        my $repng2jpeg = join '/', $iConfig->get('SystemPath'), $binary;
        -x $repng2jpeg or $iKernel->throw_io_exception($repng2jpeg);

        $ENV{'PATH'} = '/usr/bin:/usr/local/bin';
        local ( $!, *FH );
        open *FH, "| ${repng2jpeg} ${path} ${dest}"    ## no critic
            . " ${scaled_width} ${scaled_height} 90"
            or $iKernel->throw_io_exception($repng2jpeg);
        close *FH or $iKernel->throw_io_exception($repng2jpeg);
    }
    elsif ( $handler eq 'GD' ) {
        require GD;
        $ext eq 'gif' and $GD::VERSION <= 2.15 and return 1;
        my $constructor = {
            'jpg' => sub { return GD::Image->newFromJpeg( $_[0] ) },
            'gif' => sub { return GD::Image->newFromGif( $_[0] ) },
            'png' => sub { return GD::Image->newFromPng( $_[0] ) },
            }->{$ext}
            || return 1;
        my $gd = GD::Image->new( $scaled_width, $scaled_height );
        my $src = $constructor->($path);
        $gd->copyResampled( $src, 0, 0, 0, 0, $scaled_width, $scaled_height,
            $width, $height );

        local ( $!, *FH );
        open *FH, ">${dest}"    ## no critic
            or $iKernel->throw_io_exception($dest);
        binmode *FH;
        if ( $ext eq 'jpg' ) {
            print {*FH} $gd->jpeg(100) or $iKernel->throw_io_exception($dest);
        }
        elsif ( $ext eq 'gif' ) {
            print {*FH} $gd->gif() or $iKernel->throw_io_exception($dest);
        }
        elsif ( $ext eq 'png' ) {
            print {*FH} $gd->png() or $iKernel->throw_io_exception($dest);
        }
        close *FH or $iKernel->throw_io_exception($dest);
    }
    elsif ( $handler eq 'PerlMagick' ) {
        require Image::Magick;
        my $magick = Image::Magick->new;
        $magick->Read($path);
        $magick->Scale( width => $scaled_width, height => $scaled_height );
        $magick->Write($dest);
    }
    else {
        return 1;
    }
    $iUpload->set_thumbnail_size( $resno, $scaled_width, $scaled_height );
    $iUpload->save();

    return 1;
}

1;
__END__
