package IdPAccountManager::AuthenticationToken;

use strict;

use IdPAccountManager::Data::Authenticationtoken;
use IdPAccountManager::Data::Authenticationtoken::Manager;

use IdPAccountManager::Tools;
use Conf;

use Digest::MD5;

require Exporter;
my @ISA = qw(Exporter);
my @EXPORT = qw();

use Carp;

INIT {
  ## Set error mode  to non fatal
  IdPAccountManager::Data::Authenticationtoken::Manager->error_mode('return');  
 }

sub new {
    my ($pkg) = shift;
    my %args = @_;

    my $self = {};

    ## Bless AuthenticationToken object
    bless $self, $pkg;
    
    ## Object may be created either with a hashref as argument or an IdPAccountManager::Data::Authenticationtoken object
    ## Second case is usefull when fetching a set of IdPAccountManager::Data::Authenticationtoken via IdPAccountManager::Data::Authenticationtoken::Manager
    if (ref($_[0]) eq 'IdPAccountManager::Data::Authenticationtoken') {
        $self->{'persistent'} = $_[0];
    }else {
        $self->{'persistent'} = IdPAccountManager::Data::Authenticationtoken->new(%args);
    }
    
    return $self;
}

## Load an authentication token from DB
sub load {
    my $self = shift;
    
    return $self->{'persistent'}->load(speculative => 1);
}

## Get object parameter
sub get {
    my $self = shift;
    my $attribute_name = shift;
    
    return $self->{'persistent'}->$attribute_name;
}

## Set object parameters
sub set {
    my $self = shift;
    my %parameters = @_;
    
    foreach my $parameter_name (keys %parameters) {
        $self->{'persistent'}->$parameter_name($parameters{$parameter_name});
    }
    
    return 1;
}

## Save object to DB
sub save {
    my $self = shift;
       
    ## If no id is defined, it is a new account
    unless (defined $self->{'persistent'}->id) {
        $self->{'persistent'}->creation_date(time);
        $self->{'persistent'}->token(&_generate_token($self->{'persistent'}->{'email_address'}));
    }
    
    unless ($self->{'persistent'}->save()) {
        IdPAccountManager::Tools::do_log('error', "Failed to save Authenticationtoken in DB");
        return undef;
    }
}

## Delete a test account
sub delete {
    my $self = shift;
    
    unless ($self->{'persistent'}->delete()) {
        IdPAccountManager::Tools::do_log('error', "Failed to delete a Authenticationtoken in DB");
        return undef;
    }
}

## Print the content of a test account
sub print {
    my $self = shift;
    my $fd = shift || \*STDOUT;
    
    printf $fd "AuthenticationToken ID=%s; token=%s; email_address=%s; sp_entityid=%s; creation_date=%s\n",
            $self->get('id'), $self->get('token'), $self->get('email_address'), $self->get('sp_entityid'),
            &POSIX::strftime('%Y:%m:%d', localtime($self->get('creation_date')));

    return 1.
}

## list all authentication tokens
## Class method
sub list_authentication_tokens {
    my %args = @_;

    my $persistent_tokens = IdPAccountManager::Data::Authenticationtoken::Manager->get_authenticationtokens(%args);
    my $authentication_tokens;
    foreach my $persistent_token (@{$persistent_tokens}) {
        my $authentication_token = new IdPAccountManager::AuthenticationToken($persistent_token);
        push @$authentication_tokens, $authentication_token;
    }
    
    return $authentication_tokens;
}

## generate a random authentication token
sub _generate_token {
    my $salt = shift;
    my $size = shift || 20;

    ## ID is based on time + PID
    return substr(Digest::MD5::md5_hex(time.$$.$salt), -1*$size); 
}

1; # Magic true value required at end of module
__END__

=head1 NAME

IdPAccountManager::AuthenticationToken - Manage Authentication tokens used to validate test account creation requests

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 SUBROUTINES/METHODS

=head1 AUTHOR

Olivier Salaün (olivier.salaun@renater.fr)