package HPCI::Run;

### INCLUDES ##################################################################

# safe Perl
use warnings;
use strict;
use Carp;

use MooseX::Role::Parameterized;
use MooseX::Types::Path::Class qw(Dir File);

parameter theDriver => (
	isa      => 'Str',
	required => 1,
);

role {
	my $p = shift;
	my $theDriver = $p->theDriver;
	my $StageClass = "${theDriver}::Stage";

	has 'stage' => (
		is       => 'ro',
		required => 1,
		isa      => $StageClass,
		weak_ref => 1,
		handles  => {
			debug => 'debug',
			info  => 'info',
			warn  => 'warn',
			error => 'error',
			fatal => 'fatal',
		},
	);

	has 'index' => (
		is       => 'ro',
		isa      => 'Int',
		required => 1,
	);

	has 'pid' => (
		is       => 'rw',
		isa      => 'Int',
	);

	has 'unique_id' => (
		is       => 'ro',
		isa      => 'Str',
		lazy     => 1,
		init_arg => undef,
		default  => sub {
			my $self  = shift;
			my $stage = $self->stage;
			return $stage->group->_unique_name
				. '_'  . $stage->name
				. '._' . $self->index;
		},
	);

	has 'dir' => (
		is       => 'ro',
		isa      => Dir,
		init_arg => undef,
		lazy     => 1,
		default  => sub {
			my $self      = shift;
			my $stage_dir = $self->stage->dir;
			my $run_dir   = $stage_dir->subdir( $self->index );
			HPCI::_trigger_mkdir( $self, $run_dir );
			my $sym = $stage_dir->file('final_retry');
			unlink $sym if -e $sym;
			symlink $self->index, $sym;
			return $run_dir;
		},
	);

	has '_stdout' => (
		is       => 'ro',
		isa      => File,
		init_arg => undef,
		lazy     => 1,
		default  => sub {
			my $self   = shift;
			$self->dir->file( 'stdout' );
		},
	);

	has '_stderr' => (
		is       => 'ro',
		isa      => File,
		init_arg => undef,
		lazy     => 1,
		default  => sub {
			my $self   = shift;
			$self->dir->file( 'stderr' );
		},
	);

	has 'stats' => (
		is       => 'ro',
		isa      => 'HashRef[Str]',
		lazy     => 1,
		init_arg => undef,
		default  => sub {
			my $self = shift;
			return {
				map { $_ => 'unknown' } (@{ $self->stats_keys }, 'exit_status')
			}
		},
	);

	sub soft_timeout {
		my $self = shift;
		$self->info( "Sending soft timeout: " . $self->unique_id );
		my $pid = $self->pid;
		kill 'USR1', $self->pid;
	}

	sub hard_timeout {
		my $self = shift;
		my $pid = $self->pid;
		$self->info( "Sending hard timeout: " . $self->unique_id );
		kill 'KILL', $self->pid;
	}

};

1;
