package LIMS::Controller::WorkList;

use base 'LIMS::Base';

use Moose;
with (
	'LIMS::Controller::Roles::Misc',
	'LIMS::Controller::Roles::User',
	'LIMS::Controller::Roles::DataMap',
	'LIMS::Controller::Roles::FormData',
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
	
use Data::Dumper;
	
# ------------------------------------------------------------------------------
sub default : StartRunmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

	my $active_sections = $self->model('WorkList')->get_active_sections_list;
	my $request_status_options = $self->request_status_options_map;
	
	# locally defined worklists:
	if ( my $yaml = $self->get_yaml_file('worklists') ) {
		$self->tt_params( local_worklists => $yaml );
	}
	
	# print labels:
	if ( my $yaml = $self->get_yaml_file('print_labels') ) {
		$self->tt_params( print_labels => $yaml );
	}
	
    $self->tt_params(
		active_sections => $active_sections,
		request_status_options => $request_status_options,
	);
	
	return $self->tt_process;
}

# ------------------------------------------------------------------------------
sub select : Runmode {
	my $self = shift; $self->_debug_path($self->get_current_runmode);
	
	# don't need ValidateRM->check() as vars passed automatically on submit:
	my $profile = $self->validate('worklist');
    my $data = $self->get_data_from_dfv($profile); # $self->debug($data);

	my $lab_section_id = $data->{lab_section_id}
	|| return $self->redirect( $self->query->url . '/worklist' );

	{ # active investigations for this section:
		my $investigations = $self->model('WorkList')
			->get_active_investigations_for_section($lab_section_id);
		$self->tt_params( active_investigations => $investigations );
	}
	{ # lab_test status_options for this section:
		my $section_status_options
			= $self->_get_status_options_for_select($lab_section_id);
		$self->tt_params( status_options => $section_status_options );		
	}
	
	# return to default() to load lab_sections & re-display:
	return $self->forward('default');
}

# ------------------------------------------------------------------------------
sub display : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
	my $errs = shift; # warn Dumper $errs;
	
	my $lab_section_id = $self->param('id')
	|| return $self->error('no lab_section_id passed to ' . $self->get_current_runmode);
	
	# don't need ValidateRM->check() as vars passed automatically on submit:
	my $profile = $self->validate('worklist');
	my $data = $self->get_data_from_dfv($profile);
	
	# put lab_section_id into $data for model:
	$data->{lab_section_id} = $lab_section_id; # $self->debug($data);

	{ # get lab_section data:
		my $lab_section = $self->model('LabSection')->get_lab_section($lab_section_id);
		$self->tt_params( lab_section => $lab_section );
	
		# stash lab_section for request_section_notes_map() & template:
		$self->stash( lab_section => $lab_section );
	}

	my $work = $self->model('WorkList')->get_outstanding_investigations($data);

	# check we have something to do - status_option_id restriction might have been applied
	unless (@$work) {
		my $msg;
		if ( my $status_option_id = $data->{status_option_id} ) {
			my $status_option
				= $self->model('LabTest')->get_status_option($status_option_id);
			$msg = sprintf $self->messages('worklist')->{no_tests_for_status},
				uc $status_option->description;
		}
		else { # shouldn't fail if not status_option restricted, but just in case:
			$msg = sprintf $self->messages('worklist')->{no_outstanding_tests},
				$self->stash->{lab_section};
		}
		$self->flash ( info => $msg );
		my $destination =  '/worklist/select?lab_section_id=' . $lab_section_id;
		return $self->redirect($self->query->url . $destination);
	}
	
	{ # convert array of objects to array of hashrefs to prevent template lookups:
		my @data = map { $_->as_tree(deflate => 0) } @$work; # preserve datetime
		
		$self->tt_params( outstanding_investigations => \@data );
	}
	
	# get some data maps for tmpl:
	{
		my $unique_ids = $self->get_unique_ids($work); # arrayref of request_ids
		
		{ # specimens:
			my $map = $self->specimen_map($unique_ids);
			$self->tt_params( specimen_map => $map );		
		}
		{ # request_options:
			my $map = $self->request_options_map($unique_ids);
			$self->tt_params( request_options_map => $map );
		}
		{ # section notes:
			my $map = $self->request_section_notes_map($unique_ids);
			$self->tt_params( request_section_notes_map => $map );
		}
	}
	
	{ # if it's a request for data entry, set tmpl flag & get lab users:
        my $is_data_entry = (
            ( $self->query->param('display_format')
                && $self->query->param('display_format') eq 'Data Entry' )
            || 
            $self->query->param('results_entry')
        );
        
        if ( $is_data_entry ) {
            my $user_list = $self->get_lab_staff_users;
            my $status_options_map
                = $self->_get_status_options_for_data_entry($lab_section_id);
    
            $self->tt_params(
                is_results_entry => 1,
                user_list => $user_list,
                status_options_map => $status_options_map,
            );
        }
    }
    
	$self->js_validation_profile('worklist_update_status');
	
	return $self->tt_process($errs);
}

# ------------------------------------------------------------------------------
sub request_status : Runmode {
	my $self = shift;
	
	my $status_query = $self->query->param('status_query')
	|| return $self->forward('default');
	
	my $data = $self->model('WorkList')->request_status_query($status_query);
	
	# return if no requests:
	if (! @$data ) {
		my $msg = $self->messages('worklist')->{no_outstanding_requests};
		$self->flash( info => $msg );
		return $self->redirect( $self->query->url . '/worklist' );
	}

	$self->tt_params( requests => $data );	
	
	{ # get some data maps for tmpl:
		my @request_ids = map { $_->id } @$data;
		
		{ # specimens map:
			my $map = $self->specimen_map(\@request_ids);
			$self->tt_params( specimen_map => $map );		
		}
		{ # request_options:
			my $map = $self->request_options_map(\@request_ids);
			$self->tt_params( request_options_map => $map );
		}
		{ # duration map:
			my $map = $self->time_duration_map($data);
			$self->tt_params( duration_map => $map );
		}
	}
	
	return $self->tt_process('worklist/status_query.tt');
}

# ------------------------------------------------------------------------------
sub update_results : Runmode {
	my $self = shift; $self->_debug_path($self->get_current_runmode);

	# need user_id & status_option_id:
    my $dfv = $self->check_rm('display', $self->validate('worklist_update_status') )
	|| return $self->dfv_error_page;
	
	my $data = $dfv->valid;
	
	# get list of request_lab_test.id's
	my @request_lab_test_ids = $self->query->param('request_lab_test_id');
	
	if (! @request_lab_test_ids) {
		$self->flash( warning => $self->messages('worklist')->{no_lab_test_ids} );
		my $option_id = $self->query->param('status_option_id'); # warn $option_id;
		my $url = $self->query->url . '/worklist/display/' . $self->param('id')
			# have to pass 'results_entry' flag in url:
			. "?results_entry=1;status_option_id=$option_id"; 
		return $self->redirect( $url );
	}
	
	# add request_lab_test_ids to $data:
	$data->{request_lab_test_ids} = \@request_lab_test_ids;
	
	my $rtn = $self->model('Result')->update_lab_tests_from_worklist($data);
	
	if ( my $err = $rtn->{error} ) {
		return $self->error($err);
	}
	elsif ($rtn->{success}) { # warn $rtn->{success};
		$self->tt_params( updates => $rtn->{updates} );
		# get some maps:
		{
			my $users_map = $self->usernames_map;
			$self->tt_params( users_map => $users_map );
			
			my $status_options_map = $self->lab_test_status_options_map('id');
			$self->tt_params( status_options_map => $status_options_map );
		}
		$self->flash( info => $self->messages('worklist')->{update_success} );		
		return $self->tt_process('worklist/updates.tt');
	}
	else { # no db error, but also no records updated (probably unlikely unless db->err):
		$self->flash( warning => $self->messages('worklist')->{update_failure} );
		return $self->redirect( $self->query->url . '/worklist' );
	}
}

# ------------------------------------------------------------------------------
sub _get_status_options_for_data_entry {
	my ($self, $lab_section_id) = @_;
	
	# get all status options (supply 'key'):
	my $all_status_options = $self->lab_test_status_options_map('description');
	
	my $section_status_options
		= $self->lab_section_status_options_map($lab_section_id);
		
	# need to add 'complete' & 'delete' to $section_status_options:
	while ( my ($option, $data) = each %$all_status_options ) {
		next unless grep $option eq $_, qw(complete delete);
		$section_status_options->{$option} = $data->{id};
	}
	
	return $section_status_options;
}

# ------------------------------------------------------------------------------
sub _get_status_options_for_select {
	my ($self, $lab_section_id) = @_;

	my $section_status_options
		= $self->lab_section_status_options_map($lab_section_id);
	
	# get all status options (supply 'key'):
	my $all_status_options = $self->lab_test_status_options_map('description'); 

	# need to add 'new' to $section_status_options:
	$section_status_options->{new} = $all_status_options->{new}->{id};
	
	return $section_status_options;
}

1;
