package LATMOS::Accounts::Web::Model::AttrForms;

use strict;
use warnings;
use base 'Catalyst::Model';
use LATMOS::Accounts::Log;

=head1 NAME

LATMOS::Accounts::Web::Model::AttrForms - Catalyst Model

=head1 DESCRIPTION

Catalyst Model.

=cut

my $forms = {
    usersys => {
        name => 'Système',
        attrs => [ qw(
            sn givenName description
            uid uidNumber gidNumber gecos homeDirectory loginShell
            mail initials nickname
            expire
            locked
            create
            date
        ) ],
    },
    user => {
        name => 'Statut',
        attrs => [ qw(
            sn givenName description
            company
            department
            manager
            managerContact
            contratType
            expire
            snNative
            givenNameNative
            wWWHomePage
            halReference
            create
            date
        ) ],
    },
    useraddress => {
        name => 'Adresse',
        attrs => [ qw(
            initials
            mail
        ) ],
    },
    usermy => {
        name => 'My',
        attrs => [ qw(
            snNative
            givenNameNative
            wWWHomePage
            halReference
        ) ],
    },
    site => {
        name => 'Site',
        attrs => [ qw(
            description
            siteNick
            streetAddress
            postOfficeBox
            postalCode
            l
            st
            co
            facsimileTelephoneNumber
            create
            date
        ) ],
    },
    address => {
        name => 'Adresse',
        attrs => [ qw(
            isMainAddress
            telephoneNumber
            streetAddress
            postOfficeBox
            postalCode
            l
            st
            physicalDeliveryOfficeName
            site
            co
            unexported
            description
        ) ],
    },
    group => {
        name => 'Système',
        attrs => [ qw(
            gidNumber description
            managedBy
            sutype
            create
            date
        ) ],
    },
    nethost => {
        name => 'Ordinateur',
        attrs => [ qw(
            name
            description
            serialNumber
            owner
            user
            ip
            macaddr
            noDynamic
            cname
            otherName
            reverse
            create
            date
            unexported
        ) ],
    },
    netzone => {
        name => 'Zone réseau',
        attrs => [ qw(
            name
            description
            type
            net
            netExclude
            outputD
            templateD
            site
            allow_dyn
            dynFrom
            domain
            ipCount
            freeIPCount
            create
            date
            dnsRevision
            lastUpdate
            unexported
        ) ],
    },
    aliases => {
        name => 'Alias mail',
        attrs => [ qw(
            forward
            expire
            finalpoint
            parents
            created
            date
            unexported
        )],
    },
};

sub escape {
    my ($self, $text) = @_;
    $text ||= '';
    for ($text) {
        s/&/&amp;/g;
        s/</&lt;/g;
        s/>/&gt;/g;
        s/"/&quot;/g;
    }
    $text;
}

sub new {
    my ($class) = @_;
    bless({}, $class);
}

# call either OBJ or type + base

sub ACCEPT_CONTEXT {
    my ($self, $c, $form, $object, $base) = @_;
    my $new = {};
    $new->{c} = $c;
    $new->{form} = $form;
    $new->{object} = $object if (ref $object);
    $new->{base} = $base || ($object ? $object->base : undef) or return $self;
    $new->{otype} = ref $object ? $object->type : $object;
    bless($new, __PACKAGE__);
}

sub base {
    my ( $self ) = @_;
    $self->{base}
}

sub otype {
    my ($self) = @_;
    $self->{otype};
}

sub label {
    my ($self) = @_;
    $forms->{$self->{form}}->{name} || ''
}

sub attributes {
    my ($self, $for) = @_;
    grep { $_ }
    grep { $self->base->attribute($self->otype, $_) }
    @{ $forms->{$self->{form}}->{attrs} };
}

sub attr_label {
    my ($self, $attr) = @_;
    my ($hint, $label) = ('', '');
    LATMOS::Accounts::Web->config->{attrs} ||= {};
    my $htmlname = ($self->{object} ? $self->{object}->id . '_' : '') . $attr;
    if (my $attr_config = LATMOS::Accounts::Web->config->{attrs}{$attr}) {
        $label = $attr_config->{label} || '';
        #utf8::is_utf8($label) && utf8::encode($label);
        $hint = $attr_config->{hint} || '';
        #utf8::is_utf8($hint) && utf8::encode($hint);
    }
    return sprintf('<label %sfor="%s">%s</label>',
        ($hint ? sprintf('title="%s"', $self->escape($hint)) : ''),
        $self->escape($htmlname),
        $self->escape($label || $attr),
    );
}

sub attr_hint {
    my ($self, $attr) = @_;
    LATMOS::Accounts::Web->config->{attrs} ||= {};
    if (my $attr_config = LATMOS::Accounts::Web->config->{attrs}{$attr}) {
        return $attr_config->{hint} || '';
    }
    return;
}

sub attr_raw_value {
    my ($self, $attr) = @_;
    return $self->{c}->req->param($attr) ||
        ($self->{object} ? $self->{object}->get_attributes($attr) : '')
}

sub attr_field_name {
    my ($self, $attr) = @_;
    return ($self->{object}
            ? $self->{object}->id . '_'
            : ''
        ) . $attr
}

sub attr_field {
    my ($self, $attr, $type) = @_;

    my $attribute = ($self->{object}
        ? $self->{object}->attribute($attr)
        : $self->base->attribute($self->otype, $attr)) or return;

    my $htmlname = $self->escape($self->attr_field_name($attr));

    my @html_fields;
    foreach my $attr_raw_value (
        $attribute->{multiple}
            ? ((grep { $_ } $self->attr_raw_value($attr)),
                $attribute->readonly
                    ? ()
                    : ('')
            )
            : ($self->attr_raw_value($attr))) {

        my $html_id = $htmlname .
            (scalar(@html_fields) ? scalar(@html_fields) : '');

        my $html_field = '';
        for ($attribute->form_type) {
            /^textarea$/i and do {
                $html_field = sprintf(
                    '<textarea id="%s" name="%s" cols="40">%s</textarea>',
                    $self->escape($html_id),
                    $self->escape($htmlname),
                    $self->escape($attr_raw_value || ''),
                );
                last;
            };
            /^label$/i and do {
                $attr_raw_value or last;
                $html_field = $self->escape($attr_raw_value);
                $html_field =~ s/\n/<br>/g;
                $html_field .= sprintf('<input type="hidden" name="%s" value="%s">',
                    $self->escape($htmlname), ($attr_raw_value || ''));
                last;
            };
            /^date$/i and do {
                my ($date, $time) = split(/ /, $self->attr_raw_value($attr) || '');
                if ($date && $date =~ /^(\d+)-(\d+)-(\d+)$/) {
                    $date = "$3/$2/$1";
                }
                my $html = "\n" . q{<SCRIPT LANGUAGE="JavaScript" ID="js13">
                var cal13 = new CalendarPopup();
                </SCRIPT>} . "\n";
                $html .= sprintf(
                    '<input type="text" id="%s" name="%s" value="%s" size="12">',
                    $self->escape($html_id),
                    $self->escape($htmlname),
                    $self->escape($date)
                );
                $html .= q{<DIV ID="testdiv1" STYLE="position:absolute;visibility:hidden;background-color:white;layer-background-color:white;"></DIV>};
                $html .= qq|
                <A HREF="#"
                    onClick="cal13.select(document.getElementById('$html_id'),'${html_id}_anc','dd/MM/yyyy');return false;"
                    TITLE="Date"
                    NAME="${html_id}_anc" ID="${html_id}_anc">
                    <img class="attr" src="| . $self->{c}->uri_for(qw(/static icons view-calendar-day.png))
                    . qq{" style="ref"></A>
                    } . "\n";
                $html_field = $html;
                last;
            };
            /^checkbox(?::(\w+))?$/i and do {
                my $options = $1 || '';
                $html_field = sprintf('<input type="checkbox" name="%s"%s>',
                    $self->escape($htmlname),
                    $attr_raw_value ? '  checked="yes"' : ''
                ); 
                $html_field .= sprintf('<input type="hidden" name="%s">',
                    $self->escape($htmlname));
                if ($attribute->form_option('rawvalue')) {
                    $html_field .= $attr_raw_value
                        ? ' ' . $attr_raw_value
                        : ''; 
                }
                last;
            };
            /^LIST/ and do {
                my $options = $1 || '';
                my $select = sprintf('<select id="%s" name="%s">',
                    $self->escape($html_id),
                    $self->escape($htmlname)) . "\n";
                $select .= '<option value="">--</option>' . "\n"
                    unless($attribute->mandatory);
                my $value = $attr_raw_value || '';
                my $initial_observed = '';
                my @valslist;
                foreach my $val (sort $attribute->can_values) {
                    push(@valslist, {
                        val => $val,
                        disp => $attribute->display($val || ''),
                    });
                }
                foreach (sort { $a->{disp} cmp $b->{disp} } @valslist) {
                    $select .= sprintf(
                        '    <option value="%s"%s>%s</option>',
                        $self->escape($_->{val} || ''),
                        $value eq $_->{val} ? ' selected="selected"' : '',
                        $self->escape($_->{disp} || ''),
                    );
                    $select .= "\n";
                }
                $select .= "</select>\n";

                $html_field = $select;
                last;
            };
            /^text(-\w+)?(?::(\d+))?/i and do {
                my $flag = $1 || '';
                $html_field = sprintf(
                    '<input type="text" id="%s" name="%s" value="%s" size="%d">',
                    $self->escape($html_id),
                    $self->escape($htmlname),
                    $self->escape($attr_raw_value),
                    $attribute->form_option('length') || 30,
                );
                if ($flag =~ /A/) {
                    $html_field .= qq|<span id="${html_id}_auto_complete"></span>|;
                    $html_field .= "\n";
                    $html_field .= $self->{c}->prototype->auto_complete_field(
                        $html_id,
                        {
                            update => "${html_id}_auto_complete",
                            url => $self->{c}->uri_for('/ajax', 'attrvalues', $self->otype, $attr),
                            indicator => "${html_id}_stat", min_chars => 1,
                            with => "'val='+document.getElementById('$html_id').value",
                            frequency => 2,
                        }
                    );
                }
                if ($attribute->uniq) {
                    $html_field .= qq|<span class="inputvalidate" id="${html_id}_observer_uniq"></span>|;
                    $html_field .= "\n";
                    $html_field .= $self->{c}->prototype->observe_field(
                        $html_id,
                        {
                            update => "${html_id}_observer_uniq",
                            url => $self->{c}->uri_for('/ajax', 'objattrexist',
                                $self->otype, $attr),
                            frequency => 2,
                            indicator => "${html_id}_stat", min_chars => 1,
                            with => "'val='+document.getElementById('$html_id').value" .
                            ($self->{object} ? "+'&exclude=" . $self->{object}->id . "'" :
                                ''),
                        }
                    );
                    $html_field .= qq|<span style="display:none" id="${html_id}_stat">Searching...</span>|;
                }
                last;
            };
        }
        if (my $ref = $attribute->reference) {
            my $uri_part= {
                user => 'users',
                group => 'groups',
                nethost => 'nethosts',
                netzone => 'netzones',
                site => 'sites'
            }->{$ref};
            my $text;
            if ($self->base->attribute($ref, 'displayName')) {
                if ($attr_raw_value &&
                    (my $obj = $self->base->get_object($ref, $attr_raw_value)))
                {
                    $text = $obj->get_attributes('displayName');
                }
                
                $html_field .= $self->{c}->prototype->observe_field( $html_id, {
                        update => "${html_id}_span",
                        url => $self->{c}->uri_for('/ajax', 'rawattr', $ref),
                        frequency => 1,
                        with   => "'attr=displayName" .
                        "&id=' + element.options[element.selectedIndex].text",
                    }) . "\n" if ($attribute->form_type =~ /list/i);
            } elsif($attr_raw_value && $uri_part) {
                $text = sprintf(
                    '<img class="attr" src="%s" title="%s">',
                    $self->{c}->uri_for('/static', 'icons', 'arrow-right.png'),
                    $attr_raw_value,
                )
            }
            $html_field .= sprintf(qq{<span id="%s" style="margin-left: 1em">},
                "${html_id}_span");

            if (defined($text)) {
                $html_field .= $uri_part
                    ? sprintf('<a href="%s">%s</a>',
                        $self->{c}->uri_for("/$uri_part", $attribute->display($attr_raw_value)),
                        $text,)
                    : $text;
            }

            $html_field .= "</span>\n";
        }
        push(@html_fields, $html_field);
    }
    return join("<br>\n", @html_fields);
}

sub submit {
    my ($self) = @_;
    return sprintf(
        '<input type="submit" name="%s" value="Enregistrer">',
        $self->escape($self->label),
    );
}

sub write_attributes {
    my ($self) = @_;
    my @attrs;
    foreach ($self->attributes) {
        my $attr = ($self->{object}
            ? $self->{object}->attribute($_)
            : $self->base->attribute($self->otype, $_)) or next;
        $attr->readonly and next;
        push(@attrs, $_);
    }
    @attrs;
}

sub set_attrs {
    my ($self, $attrs) = @_;
    $self->{c}->req->param($self->label) || $attrs or return;
    my $prefix = $self->{object}->id . '_';
    my %fields;
    foreach ($attrs ? @{ $attrs } : $self->write_attributes) {
        my $attr = ($self->{object}
            ? $self->{object}->attribute($_)
            : $self->base->attribute($self->otype, $_)) or next;
        if ($attr->{multiple}) {
            $fields{$_} = [ grep { $_ } $self->{c}->req->param("$prefix$_") ];
        } else {
            $fields{$_} = $self->{c}->req->param("$prefix$_");
        }
    }
    $self->{object}->set_c_fields(%fields) or do {
        $self->{c}->stash->{page}{error} =
            LATMOS::Accounts::Log::lastmessage(LA_ERR);
        $self->{object}->base->rollback;
        return;
    };
    $self->{object}->base->commit;
}

=head1 AUTHOR

Thauvin Olivier

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
