#/*
# *  Copyright 2007-2008 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: Category.pm 1645 2008-02-06 15:40:18Z hikarin $
#

package Zeromin::Category;

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

sub new {
    my ( $iClass, $iKernel ) = @_;
    my $repos_path = $iKernel->get_repos_path('category');
    my $zCategory  = bless {
        __bbs  => Zeromin::BBS->new( $iKernel, { id => 0 } ),
        __cats => [],
        __rs   => $iKernel->get_repos($repos_path),
    }, $iClass;

    if ( $iKernel->get_config()->get('compatible.category') ) {
        require Zeromin::Compat::Category;
        Zeromin::Compat::Category::update( $zCategory, $iKernel );
    }

    return $zCategory;
}

sub load { $_[0]->{__rs}->load(); return 1 }

sub save {
    my ($zCat) = @_;
    my $iRepos = $zCat->{__rs};
    my $line   = $zCat->{__cats};
    if ( !@$line ) {
        $iRepos->save();
        return 0;
    }

    my $i = $iRepos->get_int('I:C._') + 1;
    for my $one (@$line) {
        $iRepos->set( "I:C.i.${i}",   $one );
        $iRepos->set( "I:C.n.${one}", $i );
        $i++;
    }
    $iRepos->set( 'I:C._', $i );
    $iRepos->save();

    @{ $zCat->{__cats} } = ();
    1;
}

sub add {
    my ( $zCat, $id ) = @_;
    push @{ $zCat->{__cats} }, $id;
    $zCat->_plugin( 'zeromin.create.category', $id );
    return;
}

sub get {
    my ( $zCat, $id ) = @_;
    my $iRepos = $zCat->{__rs};
    my $name   = $iRepos->get("I:C.i.${id}");

    if ($name) {
        {   count => $zCat->{__bbs}->category($id),
            id    => $id,
            name  => $name,
        };
    }
    else {
        {   count => 0,
            id    => 0,
            name  => '',
        };
    }
}

sub all {
    my ($zCat)   = @_;
    my $id_table = {};
    my $ret      = [];
    my $iter     = $zCat->{__rs}->iterate(
        sub {
            my ( $key, $value, $id_table ) = @_;
            if ( $key =~ /\AI:C.n\.(?:.+?)\z/xms ) {
                $id_table->{$$value} = 1;
            }
            return 0;
        },
        $id_table
    );

    require Zeromin::BBS;
    for my $id ( keys %$id_table ) {
        push @$ret, $zCat->get($id);
    }
    $ret;
}

sub all_with_page {
    my ( $zCat, $item_per_page, $offset ) = @_;

    defined $Data::Page::VERSION or require Data::Page;
    my $entries = $zCat->all();
    my $page = Data::Page->new( scalar @$entries, $item_per_page, $offset );
    return ( [ $page->splice($entries) ], $page );
}

sub get_id {
    my ( $zCat, $name ) = @_;
    return $zCat->{__rs}->get_int("I:C.n.${name}");
}

sub get_name {
    my ( $zCat, $id ) = @_;
    return $zCat->{__rs}->get("I:C.i.${id}");
}

sub exist {
    my ( $zCat, $id ) = @_;
    return $zCat->get_name($id) ? 1 : 0;
}

sub is_duplicated {
    my ( $zCat, $name ) = @_;
    return $zCat->get_id($name) ? 1 : 0;
}

sub set {
    my ( $zCat, $id, $name ) = @_;

    if ( my $old_name = $zCat->get_name($id) ) {
        my $iRepos = $zCat->{__rs};
        $iRepos->remove("I:C.n.${old_name}");
        $iRepos->set( "I:C.i.${id}",   $name );
        $iRepos->set( "I:C.n.${name}", $id );
        $iRepos->save();
        $zCat->_plugin( 'zeromin.update.category', $id );
        return 1;
    }
    0;
}

sub remove {
    my ( $zCat, $id_or_name ) = @_;
    my $id
        = $id_or_name =~ /\A\d+\z/xms
        ? ( $zCat->exist($id_or_name) ? $id_or_name : 0 )
        : $zCat->get_id($id_or_name);

    if ($id) {
        $zCat->{__bbs}->category($id) and return 0;
        my $iRepos     = $zCat->{__rs};
        my $name       = $iRepos->remove("I:C.i.${id}");
        my $removed_id = $iRepos->remove("I:C.n.${name}");
        $zCat->_plugin( 'zeromin.remove.category', $id );
        return $removed_id;
    }
    0;
}

sub _plugin {
    my ( $zCat, $at, $category_id ) = @_;
    require Zeromin::Plugin;
    my $iKernel = $zCat->{__bbs}->get_kernel();
    my $zPlugin = Zeromin::Plugin->new($iKernel);
    $zPlugin->do( $at, $zCat, [$category_id] );
    return;
}

1;
__END__
