package HTML::FormBuilder::Field;

use strict;
use warnings;
use 5.008_005;
our $VERSION = '0.01';

use Carp;
use Scalar::Util qw(weaken blessed);

use Moo;
use namespace::clean;
extends qw(HTML::FormBuilder::Base);

has data => (
    is  => 'ro',
    isa => sub {
        my $data = shift;
        croak('data should be a hashref') unless ref($data) eq 'HASH';
    },
    default => sub { {} },
);

sub BUILDARGS {
    my $class = shift;
    my %args = (@_ % 2) ? %{$_[0]} : @_;

    my $data = $args{data};

    # normalize: if 'input' is not an array, then make it as an array, so that
    # we can process the array directly
    if ( $data->{input} && ref( $data->{input} ) ne 'ARRAY' ) {
        $data->{input} = [ $data->{input} ];
    }

    return \%args;
}

sub build {
    my $self = shift;
    my $env  = shift;

    my $data = $self->{data};

    my $stacked = $env->{stacked};
    my $classes = $env->{classes};

    my $div_span     = "div";
    my $label_column = $classes->{label_column};
    my $input_column = $classes->{input_column};

    if ( $stacked == 0 ) {
        $div_span     = "span";
        $label_column = "";
        $input_column = "";
    }
    my $input_fields_html = '';

    my $stacked_attr = {};

    if ( $stacked == 1 ) {
        my $class = $data->{'class'} ? " $data->{class}" : '';

        if ( $data->{'type'} and $data->{'type'} eq 'hidden' ) {
            $stacked_attr->{class} = $class;
        }
        else {
            $stacked_attr->{class} =
              "$classes->{RowPadding} $classes->{row} clear$class";
        }
    }

    #create the field label
    if ( defined $data->{'label'} ) {
        my $label_text = $data->{'label'}->{'text'} || '';
        undef $data->{'label'}->{'text'};
        my $required_mark = delete $data->{label}{required_mark} || 0;
        my $label_html =
          $self->_build_element_and_attributes( 'label', $data->{'label'},
            $label_text, { required_mark => $required_mark },
          );

        # add a tooltip explanation if given
        if ( $data->{'label'}{'tooltip'} ) {

            # img_url is the url of question mark picture
            my $tooltip = _tooltip(
                $data->{'label'}{'tooltip'}{'desc'},
                $data->{'label'}{tooltip}{img_url}
            );

            $input_fields_html .=
qq{<div class="$classes->{extra_tooltip_container}">$label_html$tooltip</div>};
        }
        else {
            my $hide_mobile = $label_text ? "" : $classes->{hide_mobile};

            $input_fields_html .=
qq{<$div_span class="$label_column $hide_mobile form_label">$label_html</$div_span>};
        }
    }

    # create the input field
    if ( defined $data->{'input'} ) {

   #if there are more than 1 input field in a single row then we generate 1 by 1
        my $inputs = $data->{input};
        $input_fields_html .= qq{<$div_span class="$input_column">};
        foreach my $input ( @{$inputs} ) {
            $input_fields_html .= $self->_build_input( $input, $env );
        }
    }

    if ( defined $data->{'comment'} ) {
        $data->{'comment'}{'class'} ||= '';
        $input_fields_html .= '<br>'
          . $self->_build_element_and_attributes( 'p', $data->{'comment'},
            $data->{'comment'}->{'text'} );
    }

    if ( defined $data->{'error'} ) {

        my @errors =
          ref( $data->{'error'} ) eq 'ARRAY'
          ? @{ $data->{error} }
          : $data->{error};

        foreach my $error_box (@errors) {
            $input_fields_html .=
              $self->_build_element_and_attributes( 'p', $error_box,
                $error_box->{text} );
        }

    }

    #close the input tag
    if ( defined $data->{'input'} ) {
        $input_fields_html .= '</' . $div_span . '>';
    }

    if ( $stacked == 1 ) {
        $input_fields_html =
          $self->_build_element_and_attributes( 'div', $stacked_attr,
            $input_fields_html );
    }

    return $input_fields_html;
}

#####################################################################
# Usage      : build the input field its own attributes
# Purpose    : perform checking build the input field according to its own
#              characteristics
# Returns    : input field with its attributes in string
# Parameters : $input_field in HASH ref for example
#              $attributes = {'id' => 'test', 'name' => 'test', 'class' => 'myclass'}
# Comments   : check pod below to understand how to create different input fields
# See Also   :
#####################################################################
sub _build_input {
    my $self        = shift;
    my $input_field = shift;
    my $env         = shift;

    my $html = '';

    # delete this so that it doesn't carry on to the next field
    # I don't know why should delete it(undef it)
    my $heading  = delete $input_field->{'heading'};
    my $trailing = delete $input_field->{'trailing'};

    #create the filed input
    if ( eval { $input_field->can('widget_html') } ) {
        $html = $input_field->widget_html;
    }
    elsif ( $input_field->{'type'} and $input_field->{'type'} eq 'textarea' ) {
        undef $input_field->{'type'};
        my $textarea_value = $input_field->{'value'} || '';
        undef $input_field->{'value'};
        $html =
          $self->_build_element_and_attributes( 'textarea', $input_field,
            $textarea_value );
    }
    elsif ( $input_field->{'type'} ) {
        my $type = $input_field->{'type'};
        if ( $type =~ /^(?:text|password)$/i ) {
            $input_field->{'class'} .= ' text';
        }
        elsif ( $type =~ /button|submit/ ) {
            $input_field->{'class'} .= ' button';
        }

        my $tag = ( $type =~ /button|submit/ ? 'button' : 'input' );

        $html = $self->_build_element_and_attributes( $tag, $input_field );

        if ( $type =~ /button|submit/ ) {
            $html = qq{<span class="$input_field->{class}">$html</span>};
        }
    }

    if ($heading) {
        if ( $input_field->{'type'}
            && ( $input_field->{'type'} =~ /radio|checkbox/i ) )
        {
            $html .= qq{<span id="inputheading">$heading</span><br />};
        }
        else {
            $html = qq{<span id="inputheading">$heading</span>$html};
        }
    }

    if ($trailing) {
        $html .=
          qq{<span class="$env->{classes}{inputtrailing}">$trailing</span>};
    }

    return $html;
}

#####################################################################
# Usage      : _tooltip($content, $url)
# Purpose    : create tooltip html code
# Returns    : HTML
# Comments   :
# See Also   :
#####################################################################
sub _tooltip {
    my $content = shift;
    my $url     = shift;
    $content =~ s/\'/&apos;/g;    # Escape for quoting below

    return
      qq{ <a href='#' title='$content' rel='tooltip'><img src="$url" /></a>};
}

1;

=head1 NAME

HTML::FormBuilder::Fieldset - Fieldset container used by HTML::FormBuilder

=head1 SYNOPSIS

    my $form = HTML::FormBuilder->new(data => {id => 'testform});

    my $fieldset_index = $form->add_fieldset({id => 'fieldset1'});

   $form->add_field(fieldset_index, {input => {type => 'text', value => 'Join'}});

=cut

