#/*
# *  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: upload.pm 1661 2008-03-09 23:53:39Z hikarin $
#

package Zeromin2::App::upload;

use strict;

sub load_poll {
    _load_poll( { date => 'polled', name => 'BAD', template => 'Bad' }, @_ );
}

sub load_review {
    _load_poll( { date => 'reviewed', name => 'STAR', template => 'Review' },
        @_ );
}

sub load_tag {
    my ($zApp) = @_;
    $zApp->privilege( 'can_abone_res', 1 )
        or return $zApp->return_value( 1, [] );

    defined &{'Img0ch::Upload::Tag::new'} or require Img0ch::Upload::Tag;
    my $iBBS  = $zApp->bbs();
    my $key   = $zApp->key();
    my $resno = $zApp->request()->param_int('resno');
    my $param = _load_common( $zApp, $iBBS, $key, $resno );

    my $iUTag         = Img0ch::Upload::Tag->new($iBBS);
    my $tags          = $iUTag->get_utf8( $key, $resno );
    my $stack         = [];
    my $can_view_host = $zApp->privilege( 'can_view_thread_log', 1 );
    while ( my ( $tag_name, $data ) = each %$tags ) {
        my $ips = [];
        $can_view_host and map { push @$ips, { ip => $_ } } @{ $data->[1] };
        push @$stack,
            {
            name    => $tag_name,
            count   => $data->[0],
            ips     => $ips,
            ipcount => scalar(@$ips),
            };
    }

    $zApp->add_template_param(
        {   %$param,
            Tags     => $stack,
            TagCount => scalar(@$stack),
        }
    );
    return $zApp->return_value( 0, $tags );
}

sub load_ngtag {
    my ($zApp) = @_;
    $zApp->privilege( 'can_enter_control_section', 1 )
        or return $zApp->return_value( 1, [] );

    defined &{'Img0ch::Upload::Tag::new'} or require Img0ch::Upload::Tag;
    my $iBBS  = $zApp->bbs();
    my $key   = $zApp->key();
    my $resno = $zApp->request()->param_int('resno');
    my $param = _load_common( $zApp, $iBBS, $key, $resno );

    my $iUpload = Img0ch::Upload::Tag->new($iBBS);
    my $tags = $iUpload->get_ng_tag_utf8( $key, $resno );

    $zApp->add_template_param(
        {   %$param,
            NGTags     => join( "\n", @$tags ),
            NGTagCount => scalar(@$tags),
        }
    );
    return $zApp->return_value( 0, $tags );
}

sub save_ngtag {
    my ($zApp) = @_;
    $zApp->privilege( 'can_add_ngword', 1 )
        or $zApp->privilege( 'can_edit_ngword', 1 )
        or return $zApp->return_value(1);

    defined &{'Img0ch::Upload::Tag::new'} or require Img0ch::Upload::Tag;
    my $iBBS     = $zApp->bbs();
    my $iRequest = $zApp->request();
    my $key      = $zApp->key();
    my $resno    = $iRequest->param_int('resno');
    my $tags     = $iRequest->param('ngtag');

    my $iUTag = Img0ch::Upload::Tag->new($iBBS);
    $iUTag->remove_ng_tag();
    $iUTag->set_ng_tag( [ split "\n", $tags ] );
    $iUTag->save();

    return $zApp->return_value(0);
}

sub _load_poll {
    my ( $argument, $zApp ) = @_;
    $zApp->privilege( 'can_abone_res', 1 )
        or return $zApp->return_value( 1, [] );

    defined &{'Img0ch::Upload::Poll::new'}   or require Img0ch::Upload::Poll;
    defined &{'Zeromin2::Util::format_date'} or require Zeromin2::Util;
    my $iBBS     = $zApp->bbs();
    my $key      = $zApp->key();
    my $resno    = $zApp->request()->param_int('resno');
    my $iKernel  = $iBBS->get_kernel();
    my $encoding = $iKernel->get_encoding(1);
    my $param    = _load_common( $zApp, $iBBS, $key, $resno );

    my $iUPoll = Img0ch::Upload::Poll->new( $iBBS, $key );
    my $polls = $iUPoll->get( $resno, $argument->{name} );
    my $date = $argument->{date};
    for my $one (@$polls) {
        $one->{comment}
            = $iKernel->get_encoded_str( $one->{comment}, 'utf8', $encoding );
        $one->{$date} = Zeromin2::Util::format_date( $one->{polled} );
    }

    my $template = $argument->{template};
    $zApp->add_template_param(
        {   %$param,
            "PollFor${template}"      => $polls,
            "PollFor${template}Count" => scalar @$polls,
            "PollFor${template}Tag"   => $template,
        }
    );
    return $zApp->return_value( 0, $polls );
}

sub _load_common {
    my ( $zApp, $iBBS, $key, $resno ) = @_;
    my $iBBS  ||= $zApp->bbs();
    my $key   ||= $zApp->key();
    my $resno ||= $zApp->request()->param_int('resno');
    my $iKernel   = $iBBS->get_kernel();
    my $iConfig   = $iKernel->get_config();
    my $iSetting  = $iBBS->get_setting_instance();
    my $iSubject  = $iBBS->get_subject_instance();
    my $iUpload   = $iBBS->get_upload_instance($key);
    my $encoding  = $iKernel->get_encoding(1);
    my $privilege = $zApp->privilege('can_view_thread_log');
    my $extension = $iUpload->get($resno)->[0];
    my ( $width, $height, $is_image, $file_url ) = ( 0, 0, 0, '' );

    if ( $extension eq 'jpg' or $extension eq 'gif' or $extension eq 'png' ) {
        $is_image = 1;
        if ( $iUpload->get_thumbnail_size( $resno, \$width, \$height ) ) {
            $file_url = $iUpload->url( "t${resno}", $extension );
        }
        else {
            $file_url = $iUpload->url( $resno, $extension );
            ( $width, $height ) = $iUpload->scale(
                $width, $height,
                $iSetting->get('BBS_IMG_THUMBNAIL_X'),
                $iSetting->get('BBS_IMG_THUMBNAIL_Y')
            );
        }
    }
    else {
        $file_url = $iUpload->url( $resno, $extension );
    }

    return {
        BBS_TITLE => $iKernel->get_encoded_str(
            $iSetting->get('BBS_TITLE'),
            'utf8', $encoding
        ),
        DisplayPolledIP =>
            ( $privilege or !$iConfig->get('ufm.no_polled_ip') ),
        FileExtension => $extension,
        FileURL       => $file_url,
        KEY           => $key,
        ImageHeight   => $height,
        ImageWidth    => $width,
        IsImage       => $is_image,
        Resno         => $resno,
        Subject       => $iKernel->get_encoded_str(
            $iSubject->get($key)->[0],
            'utf8', $encoding
        ),
    };
}

sub load_removed_file_hash {
    my ($zApp) = @_;
    $zApp->privilege('can_remove_thread') or return $zApp->return_value(1);

    defined &{'Img0ch::Upload::Poll::new'}   or require Img0ch::Upload::Poll;
    defined &{'Zeromin2::Util::format_date'} or require Zeromin2::Util;

    my $iURemoved = Img0ch::Upload::Removed->new( $zApp->kernel() );
    my ( $hashes, $page )
        = $iURemoved->get_all_hash_with_page(
        $zApp->page_param('removed_file_hash') );
    my $ret = [];
    for my $hash (@$hashes) {
        my ( $bbs_name, $thread_key, $resno, $removed )
            = @{ $iURemoved->get($hash) };
        push @$ret,
            {
            id      => $hash,
            hash    => $hash,
            board   => $bbs_name,
            key     => $thread_key,
            resno   => $resno,
            removed => Zeromin2::Util::format_date($removed),
            };
    }

    return $zApp->return_value( 0, $ret, $page );
}

sub remove_removed_file_hash {
    my ($zApp) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_remove_thread') or return $zApp->return_value(1);

    my @param = $zApp->request()->param('hash');
    scalar @param or return $zApp->return_value(2);

    defined &{'Img0ch::Upload::Removed::new'}
        or require Img0ch::Upload::Removed;
    my $iURemoved = Img0ch::Upload::Removed->new( $zApp->kernel() );
    my $status    = {};

    for my $hash (@param) {
        if ( $iURemoved->remove($hash) ) {
            $zApp->logger( 1, 'REMOVED FILE HASH: %s', [$hash] );
            $status->{$hash} = 1;
        }
        else {
            $zApp->logger( 0, 'TRIED REMOVING FILE HASH: %s', [$hash] );
            $status->{$hash} = 0;
        }
    }

    $iURemoved->save();
    return $zApp->return_value( 0, $status );
}

sub remove_poll { _remove_poll( { name => 'BAD', log => 'POLL' }, @_ ) }

sub remove_review { _remove_poll( { name => 'STAR', log => 'REVIEW' }, @_ ) }

sub _remove_poll {
    my ( $argument, $zApp ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_remove_poll') or return $zApp->return_value(1);

    my $iRequest = $zApp->request();
    my @param    = $iRequest->param('id');
    scalar @param or return $zApp->return_value(2);

    my $resno = $iRequest->param_int('resno');
    my $tag   = $argument->{name};
    my $log   = $argument->{log};

    defined &{'Img0ch::Upload::Poll::new'} or require Img0ch::Upload::Poll;
    my $zBBS   = $zApp->bbs();
    my $bbs    = $zBBS->get_name();
    my $key    = $zApp->key();
    my $iUPoll = Img0ch::Upload::Poll->new( $zBBS, $key );
    my $status = {};

    for my $id (@param) {
        if ( $iUPoll->remove( $resno, $tag, $id ) ) {
            $zApp->logger(
                1,
                "REMOVED ${log} %s at %s/dat/%s.dat",
                [ $id, $bbs, $key ]
            );
            $status->{$id} = 1;
        }
        else {
            $zApp->logger(
                0,
                "TRIED REMOVING ${log} %s at %s/dat/%s.dat",
                [ $id, $bbs, $key ]
            );
            $status->{$id} = 0;
        }
    }

    $iUPoll->save();
    return $zApp->return_value( 0, $status );
}

sub update_removed_upload_files_as_json {
    my ($zApp) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_recreate_subject') or return $zApp->return_value(1);

    defined &{'Zeromin::Upload::new'} or require Zeromin::Upload;
    my $zUser   = $zApp->user();
    my $iKernel = $zApp->kernel();
    my @param   = $zApp->request()->param('board');
    scalar @param or return $zApp->return_value(2);

    my $status = {};
    for my $id (@param) {
        $id = Img0ch::Kernel::intval($id) || next;
        $zUser->have_privilege($id) or next;
        my $zBBS = Zeromin::BBS->new( $iKernel, { id => $id } );
        my $name = $zBBS->get_name();
        Zeromin::Upload->new($zBBS)->write_removed_data_as_json();
        $zApp->logger( 1, 'UPDATED REMOVED UPLOAD FILES AS JSON: %s',
            [$name] );
        $status->{$name} = 1;
    }

    return $zApp->return_value(0);
}

sub remove_all_poll {
    _remove_all_poll( { name => 'BAD', log => 'POLL' }, @_ );
}

sub remove_all_review {
    _remove_all_poll( { name => 'STAR', log => 'REVIEW' }, @_ );
}

sub _remove_all_poll {
    my ( $argument, $zApp ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_remove_poll') or return $zApp->return_value(1);

    my $iRequest = $zApp->request();
    my $resno    = $iRequest->param_int('resno');
    my $tag      = $argument->{name};
    my $log      = $argument->{log};

    defined &{'Img0ch::Upload::Poll::new'} or require Img0ch::Upload::Poll;
    my $zBBS   = $zApp->bbs();
    my $bbs    = $zBBS->get_name();
    my $key    = $zApp->key();
    my $iUPoll = Img0ch::Upload::Poll->new( $zBBS, $key );
    $iUPoll->remove( $resno, $tag );
    $iUPoll->save();
    $zApp->logger(
        1,
        "REMOVED ALL ${log} at %s/dat/%s.dat",
        [ $zBBS->get_name(), $key ]
    );

    return $zApp->return_value(0);
}

sub remove_tag_name_by_resno { _remove_tag_name( 0, @_ ) }

sub remove_all_tag_name { _remove_tag_name( 1, @_ ) }

sub _remove_tag_name {
    my ( $remove_all_tag, $zApp ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_remove_poll') or return $zApp->return_value(1);

    defined &{'Img0ch::Upload::Tag::new'} or require Img0ch::Upload::Tag;
    my $iBBS     = $zApp->bbs();
    my $iUTag    = Img0ch::Upload::Tag->new($iBBS);
    my $bbs      = $iBBS->get_name();
    my $iRequest = $zApp->request();
    my @names    = $iRequest->param('id');
    scalar @names or return $zApp->return_value(2);

    if ($remove_all_tag) {
        for my $name (@names) {
            $iUTag->remove_by_tag($name);
            $iUTag->save();
            $zApp->logger(
                1,
                'REMOVED FILE TAG THAT IS %s at %s',
                [ $name, $bbs ],
            );
        }
        $iUTag->save();
    }
    else {
        my $key = $zApp->key() || $zApp->return_value(1);
        my $resno = $iRequest->param_int('resno') || $zApp->return_value(1);
        for my $name (@names) {
            $iUTag->remove_by_tag( $name, $key, $resno );
            $iUTag->save();
            $zApp->logger(
                1,
                'REMOVED FILE TAG THAT IS %s at %s/%s/%s',
                [ $name, $bbs, $key, $resno ],
            );
        }
    }

    return $zApp->return_value(0);
}

sub remove_tag_by_resno {
    my ($zApp) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_remove_poll') or return $zApp->return_value(1);

    defined &{'Img0ch::Upload::Tag::new'} or require Img0ch::Upload::Tag;
    my $iBBS  = $zApp->bbs();
    my $bbs   = $iBBS->get_name();
    my $iUTag = Img0ch::Upload::Tag->new($iBBS);
    my $key   = $zApp->key() || $zApp->return_value(1);
    my $resno = $zApp->request()->param_int('resno')
        || $zApp->return_value(1);
    $iUTag->remove( $key, $resno );
    $iUTag->save();
    $zApp->logger(
        1,
        'REMOVED FILE TAG at %s/%s/%s',
        [ $bbs, $key, $resno ],
    );

    return $zApp->return_value(0);
}

sub freeze_file {
    _task(
        shift, 'can_freeze_file',
        'FREEZED UPLOADED FILE',
        'TRIED FREEZING UPLOADED FILE', 'freeze'
    );
}

sub release_file {
    _task(
        shift, 'can_release_file',
        'RELEASED UPLOADED FILE',
        'TRIED RELEASING UPLOADED FILE', 'release'
    );
}

sub _task {
    my ( $zApp, $priv_meth, $success, $fail, $method ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege( $priv_meth, 1 ) or return $zApp->return_value(1);

    my $key = $zApp->key() || return $zApp->return_value(3);
    my @param = $zApp->request()->param('resno');
    scalar @param or return $zApp->return_value(2);

    my $zBBS    = $zApp->bbs();
    my $bbs     = $zBBS->get_name();
    my $status  = {};
    my $iUpload = $zBBS->get_upload_instance($key);

    for my $resno (@param) {
        Img0ch::Kernel::intval($resno) or next;
        if ( $iUpload->$method($resno) ) {
            $zApp->logger(
                1,
                ( $success . ' %d at %s/dat/%s.dat' ),
                [ $resno, $bbs, $key ]
            );
            $status->{$resno} = 1;
        }
        else {
            $zApp->logger(
                1,
                ( $fail . ' %d at %s/dat/%s.dat' ),
                [ $resno, $bbs, $key ]
            );
            $status->{$resno} = 1;
        }
    }

    return $zApp->return_value( 0, $status );
}

1;
__END__
