#/*
# *  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: Config.pm 652 2007-05-19 12:49:46Z hikarin $
#

package Zeromin::Plugin::Config;

use strict;
use HTML::Element qw();

sub new {
    my ( $zClass, $zPlugin, $id, $bbs, $key ) = @_;
    bless {
        __bbs    => $bbs,
        __fkeys  => [],
        __html   => HTML::Element->new('div'),
        __id     => $id,
        __js     => '',
        __key    => $key,
        __plugin => $zPlugin,
        }, $zClass;
}

sub add_input_text_form {
    my ( $zPConfig, $name, $attrs ) = @_;
    $zPConfig->_add_input_form( $name, $attrs, 'text' );
}

sub add_input_password_form {
    my ( $zPConfig, $name, $attrs ) = @_;
    $zPConfig->_add_input_form( $name, $attrs, 'password' );
}

sub add_input_hidden_form {
    my ( $zPConfig, $name, $attrs ) = @_;
    $zPConfig->_add_input_form( $name, $attrs, 'hidden' );
}

sub _add_input_form {
    my ( $zPConfig, $name, $attrs, $type ) = @_;
    my $data = $zPConfig->{__plugin}->retrive(
        $zPConfig->{__id},
        $zPConfig->{__bbs},
        $zPConfig->{__key}, $name,
    );

    $attrs ||= {};
    my $tag = HTML::Element->new('input');
    while ( my ( $key, $value ) = each %{$attrs} ) {
        $tag->attr( $key, $value );
    }
    $tag->attr( 'name',  $name );
    $tag->attr( 'type',  $type );
    $tag->attr( 'value', $data->{$name} || '' );
    $zPConfig->{__html}->push_content($tag);
    push @{ $zPConfig->{__fkeys} }, $name;
    return;
}

sub add_textarea_form {
    my ( $zPConfig, $name, $attrs ) = @_;
    my $data = $zPConfig->{__plugin}->retrive(
        $zPConfig->{__id},
        $zPConfig->{__bbs},
        $zPConfig->{__key}, $name,
    );

    $attrs ||= {};
    my $tag = HTML::Element->new('textarea');
    while ( my ( $key, $value ) = each %{$attrs} ) {
        $tag->attr( $key, $value );
    }
    $tag->attr( 'name', $name );
    my $data_array = $data->{$name} || [];
    $tag->push_content( join "\n", @{$data_array} );
    $zPConfig->{__html}->push_content($tag);
    push @{ $zPConfig->{__fkeys} }, $name;
    return;
}

sub add_select_form {
    my ( $zPConfig, $name, $values, $multiple, $attrs ) = @_;
    my $data = $zPConfig->{__plugin}->retrive(
        $zPConfig->{__id},
        $zPConfig->{__bbs},
        $zPConfig->{__key}, $name,
    );

    $attrs  ||= {};
    $values ||= [];
    my $tag = HTML::Element->new('select');
    while ( my ( $key, $value ) = each %{$attrs} ) {
        $tag->attr( $key, $value );
    }
    $tag->attr( 'name', $name );
    $multiple and $tag->attr( 'multiple', 'multiple' );
    my $data_array = $data->{$name} || [];
    for my $value ( @{$values} ) {
        ( ref $value || '' ) eq 'ARRAY' or next;
        my $opt        = HTML::Element->new('option');
        my $value_attr = $value->[0];
        $opt->attr( 'value', $value_attr );
        if ( ( grep { $value_attr eq $_ } @{$data_array} ) > 0 ) {
            $opt->attr( 'selected', 'selected' );
        }
        $opt->push_content( $value->[1] );
        $tag->push_content($opt);
    }
    $zPConfig->{__html}->push_content($tag);
    push @{ $zPConfig->{__fkeys} }, $name;
    return;
}

sub add_text {
    my ( $zPConfig, $text ) = @_;
    $zPConfig->{__html}->push_content($text);
    return;
}

sub add_label {
    my ( $zPConfig, $text, $attrs ) = @_;
    my $tag = HTML::Element->new('label');
    while ( my ( $key, $value ) = each %{$attrs} ) {
        $tag->attr( $key, $value );
    }
    $tag->push_content($text);
    $zPConfig->{__html}->push_content($tag);
    return;
}

sub parse_from_hash {
    my ( $zPConfig, $config ) = @_;
    my $funcs = {
        'text'     => sub {
            my ( $zPConfig, $key, $value ) = @_;
            my $label = delete $value->{label};
            $label and $zPConfig->add_label($label);
            $zPConfig->add_input_text_form( $key, $value )
        },
        'password' => sub {
            my ( $zPConfig, $key, $value ) = @_;
            my $label = delete $value->{label};
            $label and $zPConfig->add_label($label);
            $zPConfig->add_input_password_form( $key, $value )
        },
        'hidden' => sub {
            my ( $zPConfig, $key, $value ) = @_;
            my $label = delete $value->{label};
            $label and $zPConfig->add_label($label);
            $zPConfig->add_input_hidden_form( $key, $value )
        },
        'textarea' => sub {
            my ( $zPConfig, $key, $value ) = @_;
            my $label = delete $value->{label};
            $label and $zPConfig->add_label($label);
            $zPConfig->add_textarea_form( $key, $value )
        },
    };

    while ( my ( $key, $value ) = each %$config ) {
        my $type = delete $value->{type};
        my $func = $funcs->{$type} || next;
        $func->( $zPConfig, $key, $value );
    }
    return;
}

sub set_javascript_code {
    my ( $zPConfig, $jscode ) = @_;
    $zPConfig->{__js} = $jscode;
    return;
}

sub render_html {
    my ($zPConfig) = @_;
    my $he = $zPConfig->{__html};

    for my $name ( @{ $zPConfig->{__fkeys} } ) {
        my $hidden = HTML::Element->new('input');
        $hidden->attr( 'name',  'config' );
        $hidden->attr( 'type',  'hidden' );
        $hidden->attr( 'value', $name );
        $he->push_content($hidden);
    }
    $he->push_content(
        HTML::Element->new(
            'input',
            'name'  => 'bbs',
            'type'  => 'hidden',
            'value' => $zPConfig->{__bbs},
        ),
        HTML::Element->new(
            'input',
            'name'  => 'key',
            'type'  => 'hidden',
            'value' => $zPConfig->{__key},
        ),
        HTML::Element->new(
            'input',
            'name'  => 'id',
            'type'  => 'hidden',
            'value' => $zPConfig->{__id},
        ),
    );
    @{ $zPConfig->{__fkeys} } = ();

    my $html = $he->as_HTML('<>&"\'');
    $he->delete_content();
    return \$html;
}

sub render_javascript {
    my ($zPConfig) = @_;
    return \$zPConfig->{__js};
}

sub serialize {
    my ( $zClass, $param ) = @_;
    my $ret = {};
    while ( my ( $key, $value ) = each %$param ) {
        my $reftype = ref $value || '';
        if ( $reftype eq 'ARRAY' and @$value <= 1 ) {
            $ret->{$key} = join '', @$value;
            next;
        }
        elsif ( $reftype eq '' and index( $value, "\n" ) >= 0 ) {
            $value =~ s/\r\n/\n/gxms;
            $ret->{$key} = [ split "\n", $value ];
            next;
        }
        $ret->{$key} = $value;
    }
    return $ret;
}

1;
__END__
