package LATMOS::Accounts::Bases::Sql::Aliases;

use 5.010000;
use strict;
use warnings;

use base qw(LATMOS::Accounts::Bases::Sql::objects);
use LATMOS::Accounts::Log;

our $VERSION = (q$Rev: 341 $ =~ /^Rev: (\d+) /)[0];

=head1 NAME

LATMOS::Accounts::Bases::Sql::Aliases - Mail alias object

=cut

sub _object_table { 'aliases' }

sub _key_field { 'name' }

sub _has_extended_attributes { 1 }

sub _get_attr_schema {
    my ($class, $base) = @_;

    $class->SUPER::_get_attr_schema($base,
        {
            name            => {
                ro => 1,
            },
            forward         => {
                mandatory => 1,
                multiple => 1,
                monitored => 1,
            },
            finalpoint      => { ro => 1, multiple => 1 },
            parents         => { ro => 1, },
            anyparents      => { ro => 1, },
            sameforward     => { ro => 1, multiple => 1 },
            samedestination => { ro => 1, multiple => 1 },
            user            => {
                ro => 1,
                reference => 'user',
            },
            expire    => {
                inline => 1,
                formtype => 'DATE',
            },
        }
    )
}

sub new {
    my ($class, $base, $id) = @_;
    my $sth = $base->db->prepare_cached(q{
        select name from aliases where lower(name) = lower(?)
    });
    $sth->execute($id);
    my $res = $sth->fetchrow_hashref;
    $sth->finish;
    if ($res) {
        $class->SUPER::new($base, $res->{name});
    } else {
        return;
    }
}

sub _create {
    my ($class, $base, $id, %data) = @_;
    $data{'forward'} = [ $data{'forward'} ] unless(ref $data{'forward'});
    my $sth = $base->db->prepare_cached(q{
        select name from aliases where lower(name) = lower(?)
        limit 1
        });
    $sth->execute($id);
    my $res = $sth->fetchrow_hashref;
    $sth->finish;
    if ($res) {
        $base->log(LA_ERR, "Aliases %s already exists as %s",
            $id, $res->{name});
        return;
    } else {
        return $class->SUPER::_create($base, $id, %data);
    }
}

sub get_field {
    my ($self, $field) = @_; 
    if ($field eq 'finalpoint') {
        my $sth = $self->db->prepare_cached(q{
        select forward from aliases where lower(name) = lower(?)
        limit 1
        });
        my @res = ();
        my @next = @{ $self->get_field('forward') || [] };
        while (my $next = shift(@next)) {
            $sth->execute($next);
            if (my $res = $sth->fetchrow_hashref) {
                push(@next, @{ $res->{forward} });
            } else {
                push(@res, $next);
            }
        }
        $sth->finish;
        return @res ? \@res : undef;
    }
    if ($field =~ /^(parents|anyparents|sameforward|samedestination)$/) {
        my $sth = $self->db->prepare_cached(q{
            select name from aliases where array[lower($1)] <@
                string_to_array(lower(array_to_string("forward", ',')), ',')
            });
        my @tocheck = ($field =~ /^sameforward$/
            ? $self->get_field('forward')
            : ($field =~ /^samedestination$/ 
                ? $self->get_field('finalpoint')
                : $self->id));
        my @results;
        my @already;
        while (my $next = shift(@tocheck)) {
            # endless loop detection
            grep { $next eq $_ } @already and do {
                push(@results, 'LOOP');
                next;
            };
            push(@already, $next);
            $sth->execute($next);
            while (my $res = $sth->fetchrow_hashref) {
                push(@tocheck, $res->{name});
                $res->{name} eq $self->id and next;
                push(@results, $res->{name});
            }
            $field =~ /^(parents|sameforward)$/ and last; # No recursive search
        }
        return scalar(@results) <= 1 ? $results[0] : \@results;
    }
    $self->SUPER::get_field($field);
}

sub set_fields {
    my ($self, %attrs) = @_;
    foreach (keys %attrs) {
        /^forward$/ and do {
            $attrs{$_} = [ $attrs{$_} ] unless(ref $attrs{$_});
        };
    }
    $self->SUPER::set_fields(%attrs);
}

1;

__END__

=head1 SEE ALSO

L<LATMOS::Accounts::Bases::Sql>

L<LATMOS::Accounts::Bases::Sql::Revaliases>

=head1 AUTHOR

Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.10.0 or,
at your option, any later version of Perl 5 you may have available.


=cut
