#/*
# *  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: plugin.pm 1975 2010-01-23 15:43:28Z hikarin $
#

package Zeromin2::App::plugin;

use strict;
use Zeromin::BBS qw();
use Zeromin::Plugin qw();

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

    my $zPluginBBS;
    my $zPluginGlobal = Zeromin::Plugin->new( $zApp->kernel() );
    $zPluginGlobal->load();

    my $bbs_id = 0;
    if ( my $iBBS = $zApp->bbs() ) {
        $bbs_id     = $iBBS->get_id();
        $zPluginBBS = Zeromin::Plugin->new($iBBS);
        $zPluginBBS->load();
    }

    my ( $content, $page, $class ) = $zPluginGlobal->filter_with_page(
        $zPluginBBS,
        ( $zApp->request()->param('query') || '' ),
        $zApp->page_param('plugin')
    );
    $zApp->add_template_param( { PluginClasses => $class } );
    return $zApp->return_value( 0, $content, $page );
}

sub save {
    my ( $zApp, $callFromBBS ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege( 'can_regist_plugin', $callFromBBS )
        or return $zApp->return_value(1);
    my $iRequest = $zApp->request();

    my $zPlugin = Zeromin::Plugin->new( $zApp->bbs() || $zApp->kernel() );
    $zPlugin->load();
    my @enable     = $iRequest->param('id');
    my @plugin_ids = $iRequest->param('plugin');
    my $ret        = { enable => 0, disable => 0 };
    my %enable_seen;
    map { $enable_seen{$_} = 1 } @enable;

    for my $plugin_id (@plugin_ids) {
        if ( exists $enable_seen{$plugin_id} ) {
            $zPlugin->enable($plugin_id);
            $ret->{enable}++;
        }
        else {
            $zPlugin->disable($plugin_id);
            $ret->{disable}++;
        }
    }
    $zPlugin->save();

    my ( $disable, $enable ) = ( $ret->{disable}, $ret->{enable} );
    $zApp->logger(
        1,
        'ENABLED %d PLUGINS AND DISABLED %d PLUGINS',
        [ $enable, $disable ]
    );
    $zApp->add_template_param(
        {   Disabled => $disable,
            Enabled  => $enable
        }
    );
    return $zApp->return_value(0);
}

sub load_config {
    my ( $zApp, $callFromBBS ) = @_;
    $zApp->privilege( 'can_regist_plugin', $callFromBBS )
        or return $zApp->return_value(1);
    my $iRequest = $zApp->request();

    my $iBBS    = $zApp->bbs();
    my $id      = $iRequest->param('id');
    my $key     = $iRequest->param('key') || 0;
    my $zPlugin = Zeromin::Plugin->new( $iBBS || $zApp->kernel(), $key );
    my ( $class, $method, $type ) = $zPlugin->get_plugin($id);
    $zApp->add_template_param(
        {   PluginClassName  => $class,
            PluginId         => $id,
            PluginMethodName => $method,
            PluginType       => $type,
        }
    );

    my $pluginConfigClass = $class . '::Config';
    if ( eval "use ${pluginConfigClass} qw(); 1" ) {
        my $zPConfig   = $zPlugin->set_form($id);
        my $callback   = $pluginConfigClass->register_hook();
        my $renderable = $callback->{render}->( $zPConfig, $id, $iBBS, $key );
        $zApp->add_template_param(
            {   HTML       => ${ $zPConfig->render_html() },
                JavaScript => ${ $zPConfig->render_javascript() },
                Renderable => $renderable,
            }
        );
    }
    else {
        $zApp->add_template_param( { Renderable => 0 } );
    }
    return $zApp->return_value(0);
}

sub save_config {
    my ( $zApp, $callFromBBS ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege( undef, $callFromBBS )
        or return $zApp->return_value(1);
    my $iRequest = $zApp->request();

    my $iBBS    = $zApp->bbs();
    my $id      = $iRequest->param('id');
    my $key     = $iRequest->param('key') || 0;
    my $zPlugin = Zeromin::Plugin->new( $iBBS || $zApp->kernel(), $key );
    my ( $class, $method, $type ) = $zPlugin->get_plugin($id);

    if ( $class eq '' or $method eq '' or $type eq '' ) {
        return $zApp->return_value(2);
    }
    else {
        my ( $class, $method, $type ) = $zPlugin->get_plugin($id);
        my $pluginConfigClass = $class . '::Config';

        eval "use ${pluginConfigClass} qw(); 1"
            or return $zApp->return_value(2);
        my $callback  = $pluginConfigClass->register_hook();
        my $privilege = $callback->{privilege};
        if ($privilege) {
            $privilege->( $zPlugin, $zApp->user(), $id, $iBBS, $key )
                or return $zApp->return_value(1);
        }

        require Zeromin::Plugin::Config;
        my @key   = $iRequest->param('config');
        my $param = {};
        map { $param->{$_} = [ my @array = $iRequest->param($_) ] } @key;

        my $serialized = Zeromin::Plugin::Config->serialize($param);
        $zPlugin->store( $id, undef, $key, $serialized );
        $zApp->logger(
            1,
            'SAVED PLUGIN CONFIG: %s::%s()',
            [ $class, $method ]
        );
        $zApp->add_template_param( { Done_plugin_save_config => 1 } );
        return $zApp->return_value(0);
    }
}

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

    my $iKernel   = $zApp->kernel();
    my $zBBS      = Zeromin::BBS->new( $iKernel, { bbs => '' } );
    my $zPlugin   = Zeromin::Plugin->new($iKernel);
    my $plugin_id = $zApp->request()->param('id');
    my ( $class, $method, $type ) = $zPlugin->get_plugin($plugin_id);
    my ( $unijp, $encoding ) = $zApp->unijp();
    my $allBBS    = $zBBS->all($unijp);
    my $is_global = 0;

    $zPlugin->load();
    if ( $zPlugin->is_enabled($plugin_id) ) {
        $is_global = 1;
    }
    else {
        for my $bbs (@$allBBS) {
            my $bbs_id     = $bbs->{id};
            my $iBBS       = Img0ch::BBS->new( $iKernel, { id => $bbs_id } );
            my $zPluginBBS = Zeromin::Plugin->new($iBBS);
            $zPluginBBS->load();
            $bbs->{selected} = $zPluginBBS->is_enabled($plugin_id);
        }
    }

    $zApp->add_template_param(
        {   BBSList          => $allBBS,
            IsGlobal         => $is_global,
            PluginClassName  => $class,
            PluginId         => $plugin_id,
            PluginMethodName => $method,
            PluginType       => $type,
        }
    );
    return $zApp->return_value(0);
}

sub switch_save {
    my ($zApp) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_regist_plugin') or return $zApp->return_value(1);
    my $iRequest = $zApp->request();

    my $iKernel   = $zApp->kernel();
    my $zBBS      = Zeromin::BBS->new( $iKernel, { bbs => '' } );
    my $zPlugin   = Zeromin::Plugin->new($iKernel);
    my $plugin_id = $iRequest->param('id');
    my ( $unijp, $encoding ) = $zApp->unijp();
    my $allBBS = $zBBS->all($unijp);

    my @enable           = $iRequest->param('bbs');
    my %switch_to_enable = ();
    map { $switch_to_enable{$_} = 1 } @enable;

    $zPlugin->load();
    if ( $iRequest->param('all') ) {
        $zPlugin->enable($plugin_id);
        $zPlugin->save();
    }
    else {
        $zPlugin->disable($plugin_id);
        $zPlugin->save();
        for my $bbs (@$allBBS) {
            my $bbs_id     = $bbs->{id};
            my $iBBS       = Img0ch::BBS->new( $iKernel, { id => $bbs_id } );
            my $zPluginBBS = Zeromin::Plugin->new($iBBS);
            $zPluginBBS->load();
            $switch_to_enable{$bbs_id}
                ? $zPluginBBS->enable($plugin_id)
                : $zPluginBBS->disable($plugin_id);
            $zPluginBBS->save();
        }
        $zPlugin->load();
    }

    my ( $class, $method, $type ) = $zPlugin->get_plugin($plugin_id);
    $zApp->logger(
        1,
        'SAVED ENABLE AND DISABLE PLUGIN INFO: %s::%s()',
        [ $class, $method ]
    );

    $zApp->add_template_param( { Done_plugin_switch_save => 1 } );
    return switch_load($zApp);
}

sub search { _search( 0, @_ ) }

sub install { _search( 0, @_ ) }

sub uninstall { _search( 1, @_ ) }

sub _search {
    my ( $is_uninstall, $zApp ) = @_;
    $zApp->check_csrf() or return $zApp->return_value(1);
    $zApp->privilege('can_regist_plugin') or return $zApp->return_value(1);

    my $iKernel       = $zApp->kernel();
    my $zBBS          = Zeromin::BBS->new( $iKernel, { id => 0 } );
    my $zPluginGlobal = Zeromin::Plugin->new($iKernel);

    $zPluginGlobal->load();
    my $found = $zPluginGlobal->search( '', $is_uninstall );
    $zPluginGlobal->save();

    my $bbs_range = $zApp->user()->get_current_user()->{bbs};
    my $array
        = $bbs_range
        ? $zBBS->get($bbs_range)
        : $zBBS->all();

    for my $bbs ( @{$array} ) {
        my $zPlugin = Zeromin::Plugin->new( $zApp->kernel );
        $zPlugin->set_bbs_id( $bbs->{id} );
        $zPlugin->copy($zPluginGlobal);
        $zPlugin->save();
    }

    $found
        and $zApp->logger( 1,
        $is_uninstall ? 'REMOVED %d PLUGINS' : 'FOUND NEW %d PLUGINS',
        [$found] );
    $zApp->add_template_param( { Found => $found } );
    return $zApp->return_value(0);
}

1;
__END__
