package JobsManager;

use strict;
use warnings;

use DBI;
use DateTime;

use lib qw(Core);

use Database;

use Configuration;

my $jobs_manager = undef;

sub new {
    my ($class) = @_;
    
    return $jobs_manager if(defined($jobs_manager));
    
    my $self = {
        _id => undef,
        _database => Database->new($CONFIG->{HOSTNAME}, $CONFIG->{PORT}, $CONFIG->{DATABASE}, $CONFIG->{USERNAME}, $CONFIG->{PASSWORD})
    };
    
    $jobs_manager = bless $self, $class;
    return $jobs_manager;
}

sub exist {
    my ($self, $id) = @_;
    
    my $result = 0;
    
    my $query = sprintf("SELECT COUNT(id) FROM casp13.servers_distribution WHERE (id = %d)", $id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth) && ($sth->rows() > 0)) {
        my ($count) = $sth->fetchrow_array();
        
        $result = ($count == 1) ? 1 : 0;
    }
    
    return $result;
}

sub info {
    my ($self, $id) = @_;
    
    my %result = (
        ID => '',
        GROUPS_ID => '',
        TARGETS_ID => '',
        STATUS => '',
        UID => '',
        REQUEST_TIME => '',
        RESPONSE_TIME => '',
        DATE => ''
    );
    
    return %result if(! $self->exist($id));
    
    my $query = sprintf("SELECT id, groups_id, targets_id, status, uid, request_time, response_time, date FROM casp13.servers_distribution WHERE (id = %d)", $id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth) && ($sth->rows() > 0)) {
        ($result{ID}, $result{GROUPS_ID}, $result{TARGETS_ID}, $result{STATUS}, $result{UID}, $result{REQUEST_TIME}, $result{RESPONSE_TIME}, $result{DATE}) = $sth->fetchrow_array();
    }
    
    return %result;
}

sub register {
    my ($self, $targets_id, $groups_id, $uid) = @_;
    
    my $result = 0;
    
    my $query = sprintf("INSERT INTO casp13.servers_distribution (groups_id, targets_id, uid) VALUES (%d, %d, '%s');", $groups_id, $targets_id, $uid);
    #my $query = sprintf("BEGIN JOB_REGISTRATION; LOCK TABLE casp13.servers_distribution IN EXCLUSIVE MODE; INSERT INTO casp13.servers_distribution (groups_id, targets_id, uid) VALUES (%d, %d, '%s'); SELECT MAX(id) FROM casp13.servers_distribution; COMMIT JOB_REGISTRATION", $groups_id, $targets_id, $uid);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth)) {
        my $query = sprintf("SELECT id FROM casp13.servers_distribution WHERE (uid = '%s')", $uid);
        my $sth = $self->{_database}->query($query);
        
        ($result) = $sth->fetchrow_array();
    }
    
    return $result;
}

sub request {
    my ($self, $id) = @_;
    
    my $result = 0;
    
    return $result if(! $self->exist($id));
    
    my $query = sprintf("UPDATE casp13.servers_distribution SET status = 2, request_time = now() WHERE (id = %d)", $id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth)) { $result = 1; }
    
    return $result;
}

sub response {
    my ($self, $id) = @_;
    
    my $result = 0;
    
    return $result if(! $self->exist($id));
    
    my $query = sprintf("UPDATE casp13.servers_distribution SET status = 3, response_time = now() WHERE (id = %d)", $id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth)) { $result = 1; }
    
    return $result;
}

sub last_job_for_group {
    my ($self, $group_id) = @_;
    
    my %result = ();
    
    my $query = sprintf("SELECT id FROM casp13.servers_distribution WHERE (groups_id = %d) AND (request_time < now()) ORDER BY request_time DESC LIMIT 1", $group_id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth) && ($sth->rows() > 0)) {
        my ($id) = $sth->fetchrow_array();
        
        %result = $self->info($id);
    }
    
    return %result;
}

sub get_job {
    my ($self, $group_id, $target_id) = @_;
    
    my %result = ();
    
    my $query = sprintf("SELECT id FROM casp13.servers_distribution WHERE (groups_id = %d) AND (targets_id = %d) AND (request_time < now()) ORDER BY request_time DESC LIMIT 1", $group_id, $target_id);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth) && ($sth->rows() > 0)) {
        my ($id) = $sth->fetchrow_array();
        
        %result = $self->info($id);
    }
    
    return %result;
}

sub distributed_jobs {
    my ($self, $target_id, $group_id) = @_;
    
    my @jobs = ();
    
    my $target_query = ($target_id > 0) ? sprintf(" AND (sd.targets_id = %d)", $target_id) : '';
    my $group_query = ($group_id > 0) ? sprintf(" AND (sd.groups_id = %d)", $group_id) : '';
    
    my $query = sprintf("SELECT sd.id, sd.status, sd.uid, sd.request_time, sd.response_time, sd.date, t.name, g.name FROM casp13.servers_distribution sd JOIN casp13.targets t ON (t.id = sd.targets_id) JOIN casp13.groups g ON (g.id = sd.groups_id) WHERE (1=1) %s %s ORDER BY sd.date DESC", $target_query, $group_query);
    my $sth = $self->{_database}->query($query);
    
    if(defined($sth) && ($sth->rows() > 0)) {
        my $index = 1;
        while(my($id, $status, $uid, $request_time, $response_time, $date, $target_name, $group_name) = $sth->fetchrow_array()) {
            $request_time = !defined($request_time) ? '-' : (substr($request_time, 0, 10) . "<br>" . substr($request_time, 11, 8));
            $response_time = !defined($response_time) ? '-' : (substr($response_time, 0, 10) . "<br>" . substr($response_time, 11, 8));
            $date = !defined($date) ? '' : (substr($date, 0, 10) . "<br>" . substr($date, 11, 8));
            
            push(@jobs, {
                    ID => $id,
                    INDEX => $index,
                    STATUS => $status,
                    UID => $uid,
                    REQUEST_TIME => $request_time,
                    RESPONSE_TIME => $response_time,
                    DATE => $date,
                    TARGET_NAME => $target_name,
                    GROUP_NAME => $group_name,
            	}
            );
            $index++;
        }
    }
    
    return @jobs;
}

1;
