#/*
# *  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: user.pm 350 2007-03-16 13:25:21Z hikarin $
#

package Zeromin::App::user;

use strict;

sub load {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() || return { code => 1 };
    my $iRequest = $zApp->request();
    my $sub      = {
        'individual' => sub {
            my ( $zUser, $iKernel ) = @_;
            $zUser->can_enter_user_section() or return;
            return $zUser->get_users();
        },
        'group' => sub {
            my ( $zUser, $iKernel ) = @_;
            $zUser->can_enter_ugroup_section() or return;
            return $zUser->get_groups();
        },
        'log' => sub {
            my ( $zUser, $iKernel ) = @_;
            require Zeromin::Log::Action;
            my $zLog = Zeromin::Log::Action->new($iKernel);
            $zLog->load();
            return $zLog->all($zUser);
        },
    }->{ $iRequest->param('type') };

    if ($sub) {
        my $ret = $sub->( $zUser, $zApp->kernel() ) or return { code => 1 };
        if ( my $offset = $iRequest->param_int('offset') ) {
            my $item = $iRequest->param_int('item') || 10;
            $ret = $zApp->paging_from_array( $ret, $offset, $item );
        }
        return { code => 0, content => $ret };
    }
    else {
        return { code => 1 };
    }
}

sub save {
    my ($zApp) = @_;
    my $zUser    = $zApp->user or return { code => 1 };
    my $iRequest = $zApp->request();
    my $id       = $iRequest->param_int('id');
    my $error    = {};
    my $param    = {};

    if ( $iRequest->param('type') eq 'individual' ) {
        _validate_user_param( $zApp, $zUser, $param, $error )
            or return $error;
        my $user = $zUser->get_user($id);
        my $name = $param->{name};
        my $mail = $param->{mail};
        my $pass = $param->{pass};
        my $gid  = $param->{gid};
        if ( defined $user->{id} ) {
            $zUser->can_edit_user() or return { code => 1 };
            $zUser->edit(
                $id,
                {   mail => $mail,
                    pass => $pass,
                    gid  => $gid,
                }
            );
            $zUser->save();
            $zApp->logger(
                1,
                'EDIT USER: %s(%s) with %s belongs %d',
                [ $name, $mail, $pass, $gid ],
            );
            { code => 0 };
        }
        else {
            $zUser->can_create_user() or return { code => 1 };
            $zUser->add(
                {   name => $name,
                    mail => $mail,
                    pass => $pass,
                    gid  => $gid,
                }
            ) or return { code => 10 };
            $zUser->save();
            $zApp->logger(
                1,
                'CREATE USER: %s(%s) with %s belongs %d',
                [ $name, $mail, $pass, $gid ],
            );
            { code => 0, id => $zUser->get_user_id($name) };
        }
    }
    else {
        _validate_ugroup_param( $zApp, $zUser, $param, $error )
            or return $error;
        my $ugroup       = $zUser->get_group($id);
        my $name         = $param->{name};
        my $bbs          = $param->{bbs};
        my $user_priv    = $param->{user_priv};
        my $cap_priv     = $param->{cap_priv};
        my $bbs_priv     = $param->{bbs_priv};
        my $subject_priv = $param->{subject_priv};
        my $setting_priv = $param->{setting_priv};
        my $thread_priv  = $param->{thread_priv};
        my $pool_priv    = $param->{pool_priv};
        my $archive_priv = $param->{archive_priv};
        my $res_priv     = $param->{res_priv};
        my $meta_priv    = $param->{meta_priv};
        my $cntl_priv    = $param->{cntl_priv};
        my $cat_priv     = $param->{cat_priv};
        my $view_priv    = $param->{view_priv};
        my $plugin_priv  = $param->{plugin_priv};

        if ( $ugroup->{id} ) {
            $zUser->can_edit_ugroup() or return { code => 1 };
            $zUser->edit_group(
                $id,
                {   name      => $name,
                    bbs       => $bbs,
                    privilege => {
                        user     => $user_priv,
                        cap      => $cap_priv,
                        bbs      => $bbs_priv,
                        subject  => $subject_priv,
                        setting  => $setting_priv,
                        thread   => $thread_priv,
                        pool     => $pool_priv,
                        archive  => $archive_priv,
                        res      => $res_priv,
                        meta     => $meta_priv,
                        control  => $cntl_priv,
                        category => $cat_priv,
                        view     => $view_priv,
                        plugin   => $plugin_priv,
                    },
                }
            );
            $zUser->save();
            $zApp->logger(
                1,
                'EDIT USER GROUP: %s belongs %d',
                [ $name, $bbs ],
            );
            { code => 0 };
        }
        else {
            $zUser->can_create_ugroup() or return { code => 1 };
            $zUser->add_group(
                {   name      => $name,
                    bbs       => $bbs,
                    privilege => {
                        user     => $user_priv,
                        cap      => $cap_priv,
                        bbs      => $bbs_priv,
                        subject  => $subject_priv,
                        setting  => $setting_priv,
                        thread   => $thread_priv,
                        pool     => $pool_priv,
                        archive  => $archive_priv,
                        res      => $res_priv,
                        meta     => $meta_priv,
                        control  => $cntl_priv,
                        category => $cat_priv,
                        view     => $view_priv,
                        plugin   => $plugin_priv,
                    },
                }
            );
            $zUser->save();
            $zApp->logger(
                1,
                'CREATE USER GROUP: %s belongs %d',
                [ $name, $bbs ],
            );
            { code => 0, id => $zUser->get_group_id($name) };
        }
    }
}

sub remove {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() || return { code => 1 };
    my $iRequest = $zApp->request();
    my $status   = {};
    my ( $type, $method );

    if ( $iRequest->param('type') eq 'individual' ) {
        $zUser->can_remove_user() or return { code => 1 };
        $type   = 'USER';
        $method = 'remove';
    }
    else {
        $zUser->can_remove_ugroup() or return { code => 1 };
        $type   = 'USER GROUP';
        $method = 'remove_group';
    }

    my @ids = $iRequest->param('id');
    for my $id (@ids) {
        $id = Img0ch::Kernel::intval($id);
        $id == 1 and next;
        if ( $zUser->$method($id) ) {
            $zUser->save;
            $zApp->logger( 1, "REMOVE $type: \%s", [$id] );
            $status->{$id} = 1;
        }
        else {
            $zApp->logger( 0, "TRIED REMOVING INEXIST $type: \%s", [$id] );
            $status->{$id} = 0;
        }
    }
    { code => 0, removed => $status };
}

sub get {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() || return { code => 1 };
    my $iRequest = $zApp->request();
    my $id       = $iRequest->param('id');

    if ( $iRequest->param('type') eq 'individual' ) {
        $zUser->can_enter_user_section() or return { code => 1 };
        return $zUser->get_user($id);
    }
    else {
        $zUser->can_enter_ugroup_section() or return { code => 1 };
        return $zUser->get_group($id);
    }
}

sub _validate_user_param {
    my ( $zApp, $zUser, $param, $error ) = @_;
    my $iRequest = $zApp->request();

    my $name = $iRequest->param('name');
    if ( $name eq '' ) {
        $zApp->logger( 0, 'NO USER NAME WAS SET' );
        %{$error} = ( code => 2 );
        return 0;
    }
    my $mail = $iRequest->param('mail');
    if ( $mail eq '' ) {
        $zApp->logger( 0, 'NO USER MAIL WAS SET' );
        %{$error} = ( code => 3 );
        return 0;
    }
    my $group = Img0ch::Kernel::intval( $iRequest->param('group') );
    if ( !$group ) {
        $zApp->logger( 0, 'NO USER GROUP WAS SET' );
        %{$error} = ( code => 4 );
        return 0;
    }
    my $pass = $iRequest->param('pass');
    if ( $pass eq '' ) {
        $zApp->logger( 0, 'NO USER PASS WAS SET' );
        %{$error} = ( code => 5 );
        return 0;
    }
    my $conf = $iRequest->param('confirm');
    if ( $conf eq '' ) {
        $zApp->logger( 0, 'NO USER CONFIRM PASS WAS SET' );
        %{$error} = ( code => 6 );
        return 0;
    }
    if ( $mail !~ /\A[\w\-\.]+\@[\w\-\.]+\z/xms ) {
        $zApp->logger( 0, 'INVALID USER MAIL WAS SET' );
        %{$error} = ( code => 7 );
        return 0;
    }
    if ( $pass ne $conf ) {
        $zApp->logger( 0, 'NOT EQUAL USER PASS AND USER CONFIRM PASS' );
        %{$error} = ( code => 8 );
        return 0;
    }
    if ( $zUser->get_group_name($group) eq '' ) {
        $zApp->logger( 0, 'INVALID USER GROUP WAS SET' );
        %{$error} = ( code => 9 );
        return 0;
    }

    $param->{name} = $name;
    $param->{mail} = $mail;
    $param->{pass} = $pass;
    $param->{gid}  = $group;
    1;
}

sub _validate_ugroup_param {
    my ( $zApp, $zUser, $param, $error ) = @_;
    my $iRequest = $zApp->request();

    my $name = $iRequest->param('name');
    if ( $name eq '' ) {
        $zApp->logger( 0, 'NO USER GROUP NAME WAS SET' );
        %$error = ( code => 2 );
        return 0;
    }
    if ( $name eq 'Administrators' ) {
        $zApp->logger( 0, 'CANNOT EDIT "Administrators"' );
        %$error = ( code => 3 );
        return 0;
    }

    my @bbs = $iRequest->param('bbs');
    $param->{name}         = $name;
    $param->{bbs}          = \@bbs;
    $param->{user_priv}    = $iRequest->param_int('user_priv');
    $param->{cap_priv}     = $iRequest->param_int('cap_priv');
    $param->{bbs_priv}     = $iRequest->param_int('bbs_priv');
    $param->{subject_priv} = $iRequest->param_int('subject_priv');
    $param->{setting_priv} = $iRequest->param_int('setting_priv');
    $param->{thread_priv}  = $iRequest->param_int('thread_priv');
    $param->{pool_priv}    = $iRequest->param_int('pool_priv');
    $param->{archive_priv} = $iRequest->param_int('archive_priv');
    $param->{res_priv}     = $iRequest->param_int('res_priv');
    $param->{meta_priv}    = $iRequest->param_int('meta_priv');
    $param->{cntl_priv}    = $iRequest->param_int('control_priv');
    $param->{cat_priv}     = $iRequest->param_int('category_priv');
    $param->{view_priv}    = $iRequest->param_int('view_priv');
    $param->{plugin_priv}  = $iRequest->param_int('plugin_priv');
    1;
}

1;
__END__
