package LATMOS::Accounts::Web::Controller::Users;

use strict;
use warnings;
use base 'Catalyst::Controller';

use Date::Parse;
use DateTime;
use DateTime::TimeZone;
use POSIX;

=head1 NAME

LATMOS::Accounts::Web::Controller::Users - Catalyst Controller

=head1 DESCRIPTION

Catalyst Controller.

=head1 METHODS

=cut


=head2 index 

=cut

sub index : Private {
    my ( $self, $c ) = @_;

    $c->stash->{ofilter} = $c->model('AttrFilter', 'user');
    $c->stash->{page}{title} = "Liste des utilisateurs";
}

sub users :PathPart('users') Chained('/') CaptureArgs(1) {
    my ( $self, $c, $username ) = @_;

    $c->stash->{subform} = (split('/', ($c->req->path ||'')))[2];

    my $base = $c->model('Accounts')->db;

    $c->stash->{page}{title} = "Utilisateur :: $username";
    $c->stash->{username} = $username;
    $c->stash->{user} = $base->get_object('user', $username) or do {
        $c->forward('/no_object');
        return;
    };
    $c->stash->{page}{title} = "Utilisateur :: $username";

    if ($c->req->param('make_active')) {
        $c->stash->{user}->set_c_fields('unexported' => undef);
        $base->commit;
    }
    if ($c->req->param('make_inactive')) {
        $c->stash->{user}->set_c_fields('unexported' => 1);
        $base->commit;
    }
    if ($c->req->param('delete')) {
        $base->delete_object('user', $username);
        $base->commit;
        $c->res->redirect('/users');
        return;
    }
}

sub Display :PathPart('') Chained('users') Args(0) {
    my ( $self, $c ) = @_;

    if ($c->config->{features}->{user_employment}) {
        #Replace standard RH form by employment
        $c->detach('/users/employment/index');
        return 1;
    }

    $c->stash->{form} = $c->model('AttrForms', 'user', $c->stash->{user});
    $c->stash->{form}->set_attrs;

}

sub Sys :PathPart('sys') Chained('users') Args(0) {
    my ( $self, $c ) = @_;

    $c->stash->{template} = 'users/Display.tt';

    $c->stash->{form} = $c->model('AttrForms', 'usersys', $c->stash->{user});
    $c->stash->{form}->set_attrs;

}

sub Mail :PathPart('mail') Chained('users') Args(0) {
    my ($self, $c) = @_;

    my $base = $c->model('Accounts')->db;

    $c->stash->{db} = $base;
    $c->stash->{template} = 'users/mail.tt';

    if ($c->req->param('usermail')) {

        my %expaliases = map { $_ => 1 } $c->req->param('expaliases');
        foreach my $alias ($c->stash->{user}->get_attributes('aliases'), $c->stash->{user}->id) {
            my $oalias = $base->get_object('aliases', $alias) or next;
            if (($expaliases{ $alias } || 0) xor ($oalias->get_c_field('exported') || 0)) {
                $oalias->set_c_fields('unexported' => ($expaliases{ $alias } ? undef : 1)) or do {
                    $base->rollback;
                    last;
                };
            }
        }
        $c->stash->{user}->set_c_fields(
            mail => $c->req->param('mail') || undef,
            aliases => [ grep { $_ } $c->req->param('aliases') ],
            revaliases => $c->req->param('revaliases') || undef,
            forward => $c->req->param('forward') || undef,
        ) or do {
            $base->rollback;
            return;
        };

        $base->commit;
    }
}

sub Password :PathPart('passwd') Chained('users') Args(0) {
    my ($self, $c) = @_;
    my $username = $c->stash->{username};

    my $base = $c->model('Accounts')->db;

    $c->stash->{template} = 'users/passwd.tt';
    if ($c->req->param('passwd')) {
        if ($base->check_acl($c->stash->{user}, 'userPassword', 'w')) {
            if ($c->req->param('passwd') eq ($c->req->param('cpasswd') || '')) {
                $c->stash->{pmerror} = $c->forward('change_password',
                    [ $username, $c->req->param('passwd') ] ) || 'Mot de passe changé';
            } else {
                $c->stash->{pmerror} = 'Mot de passe différents';
            }
        }
    }
}

sub Groups :PathPart('groups') Chained('users') Args(0) {
    my ($self, $c) = @_;
    my $username = $c->stash->{username};
    $c->stash->{template} = 'users/groups.tt';

    my $base = $c->model('Accounts')->db;

    # list of group for which users can be added
    my %ingroups = map { $_ => 1 } @{ $c->stash->{user}->get_c_field('memberOf') || []};
    if ($c->req->param('addgroup')) {
        $c->stash->{user}->set_c_fields('memberOf', [ keys %ingroups, $c->req->param('addgroup') ]);
        $c->stash->{user}->base->commit;
        # reread:
        %ingroups = map { $_ => 1 } @{ $c->stash->{user}->get_c_field('memberOf') || []};
    } elsif ($c->req->param('delgroup')) {
        $c->stash->{user}->set_c_fields('memberOf',
            [ grep { $_ ne $c->req->param('delgroup') } keys %ingroups ]
        );
        $c->stash->{user}->base->commit;
        %ingroups = map { $_ => 1 } @{ $c->stash->{user}->get_c_field('memberOf') || []};
    }

    $c->stash->{othergroups} = [ grep { ! $ingroups{$_} } $base->list_objects('group') ];
}

sub AddressCommon :PathPart('') Chained('users') CaptureArgs(0) {
    my ($self, $c) = @_;

    my $username = $c->stash->{username};

    my $base = $c->model('Accounts')->db;


    if ($c->req->param('main')) {
        if (my $ad = $base->get_object('address',
                $c->req->param('main'))) {
            $ad->base->commit;
        }
    }
    $c->stash->{template} = 'users/address.tt';
}

sub Address :PathPart('address') Chained('AddressCommon') Args(0) {
    my ($self, $c) = @_;

    my $base = $c->model('Accounts')->db;
    my $username = $c->stash->{username};

    if ($c->req->param('del_addr')) {
        $base->delete_object('address', $c->req->param('del_addr'));
        $base->commit;
    } elsif ($c->req->param('add_addr')) {
        my $addname = $username . join('', map
            {('a'..'z')[rand(26)]}(0..4));
        if ($base->create_c_object('address',
                $addname,
                user => $username,
            )) {
            $base->commit;
            $c->res->redirect($c->uri_for($username, 'address',
                    $addname));
            return;
        }
    }
    my ($main) = $c->stash->{user}->get_attributes('otheraddress');
    if ($main) {
        $c->detach('AddressDisplay', [ $main ]);
    }
}

sub AddressDisplay :PathPart('address') Chained('AddressCommon') Args(1) {
    my ($self, $c, $arg) = @_;

    my $base = $c->model('Accounts')->db;

    $c->stash->{address} = $base->get_object('address', $arg);
    $c->stash->{form} = $c->model('AttrForms', 'address',
        $c->stash->{address});
    $c->stash->{form}->set_attrs;
}

sub my :PathPart('my') Chained('users') Args(0) {
    my ($self, $c) = @_;
}

sub change_password : Private {
    my ($self, $c, $username, $password) = @_;

    my $base = $c->model('Accounts')->db;
    $c->stash->{user} = $base->get_object('user', $username) or do {
        $c->forward('/no_object');
        return "Cannot get user object";
    };

    my $sync = $c->model('Accounts')->sync_access;

    # This is widelly burk:
    # synchaccess do not manage connect() at time, opening a
    # backdoor then :\
    foreach ($sync->bases) { $_->{_user} = undef }

    my $suser = $sync->get_object_ifexists('user', $username);
    my $msg = $c->stash->{user}->check_password($password);
    if ($msg ne 'ok') {
        return $msg . ', mot de passe inchangé';
    } elsif ($suser && $suser->_set_password($password)) {
        $sync->commit;
        return;
    } else {
        return 'Erreur lors du changement de mot de passe';
    }
}

=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;
