package Epoll::Controller::Ballot;

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

=head1 NAME

Epoll::Controller::Ballot - Catalyst Controller

=head1 DESCRIPTION

Catalyst Controller.

=head1 METHODS

=cut


=head2 index 

=cut

sub begin : Private {
    my ( $self, $c ) = @_;
    $c->model('Vote')->rollback;
}

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

    $c->res->redirect($c->uri_for('/'));
}

sub default : Private {
    my ( $self, $c, undef, $id ) = @_;

    $c->stash->{voteid} = $id;
    my $poll = $c->model('Vote')->poll($id);
    my $puid = $poll->uid;

    if ($poll->status ne 'RUNNING') {
        $c->stash->{template} = 'ballot/closed.tt';
        return;
    }

    my $mail = $c->session->{$puid}{mail} || $c->req->param('mail');
    my $password = $c->session->{$puid}{password} || $c->req->param('password');

    if (!$c->model('Vote')->poll($id)->auth_voting($mail, $password)) {
        $c->stash->{page}{title} = $poll->info('label') . ': ' . $c->localize('Login');
        $c->session->{$puid} = undef;
        $c->stash->{template} = 'ballot/login.tt';
        if (defined($c->req->param('password'))) {
            # show login failure:
            $c->stash->{login_failure} = 1;
        }
        return;
    }

    $c->session_expire_key( $puid => 600 );
    $c->session->{$puid}{mail} = $mail;
    $c->session->{$puid}{password} = $password;
    $c->session->{mypoll}{$puid} ||= 0;

    $c->stash->{page}{title} = $poll->info('label') . ': ' . $c->localize('Ballot');

    # login succeed, but those this user has already voted
    if (my $date = $poll->voting_has_sign($mail)) {
        $c->stash->{mail} = $c->session->{$puid}{mail};
        $c->stash->{template} = 'ballot/signed.tt';
        $c->stash->{signed_date} = $date;
        $c->session->{$puid} = undef;
        return;
    }

    my $vote = $c->model('Vote');
    my %choices;
    foreach ($poll->choices_keys) {
        $choices{$_} = $poll->choice($_)->info->{label};
    }
    $c->stash->{choices} = { %choices };
    $c->stash->{sbal} = { map { $_ => 1 } $c->req->param('sbal') };
    $c->stash->{fsbal} = [ grep { $_ } map {
        s/^\s+//;
        s/\s+$//;
        s/\s+/ /g;
        lc($_)
    } ($c->req->param('fsbal')) ];
    $c->stash->{esbal} = [ grep { $_ } $c->req->param('esbal') ];

    $c->request->parameters->{fsbal} = $c->stash->{fsbal};

    my @sbalval = grep { $_ } map { lc($choices{$_} || '') } $c->req->param('sbal');

    my @ballot = grep { $_ } (
        @sbalval,
        @{$c->stash->{fsbal} || []},
        @{$c->stash->{esbal} || []},
    );
    if (scalar(@ballot) > $poll->info('choice_count')) {
        $c->req->parameters->{'ballot'} = '';
        $c->stash->{vote_error} = $c->localize('Only ') .
            $poll->info('choice_count') . ' ' . $c->localize('possible choices');
        return;
    }
    {
        my %uniq;
        foreach(@ballot) {
            $uniq{lc($_)} ||= 0; # avoid undef
            $uniq{lc($_)}++;
        }
        my @twices = grep { $uniq{$_} > 1 } (sort keys %uniq);
        if (scalar(@twices)) {
            $c->req->parameters->{'ballot'} = '';
            $c->stash->{vote_error} = $c->localize('One or more values are duplicated:') .
                join(' ,', map { qq'"$_"' } @twices);
            return;
        }
    }

    if ($c->req->param('confirm')) {
        $c->stash->{ballotid} = $poll->register_ballot(
            $mail,
            [ @ballot ],
            $c->req->address,
        ); # TODO trap error
        $c->forward(
            q'Epoll::View::Mail', 'render',
            [ 'ballot_confirm.tt', {
                From => $mail,
                To => $mail,
                Subject => $c->localize('Vote confirmation:') . $poll->info('label'),
                mail => {
                    ballotid => $c->stash->{ballotid},
                    voteid => $id,
                }
            } ]
        ) unless($poll->info->{no_mail_confirm_vote});

        $c->stash->{template} = 'ballot/done.tt';
    }
}

sub end : Private {
    my ($self, $c) = @_;
    if ($c->res->body) { return }
    else { $c->forward(qw/Epoll::View::TT/) }
}

=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 or CeCILL.

=cut

1;
