package LIMS::Controller::Roles::History;

use Moose::Role;

has history => (
    is         => 'ro',
    isa        => 'ArrayRef[Str]',
	lazy       => 1, # needed to avoid 'Can't use an undefined value as an ARRAY reference'
    default    => sub { [] },
	traits     => ['Array'],
	handles => {
		add_history     => 'push',
		count_histories => 'count',
		all_histories   => 'elements',
	},
);

has formatted_output => (
    is         => 'ro',
    isa        => 'ArrayRef[HashRef]',
	lazy       => 1, # needed to avoid 'Can't use an undefined value as an ARRAY reference'
    default    => sub { [] },
	traits     => ['Array'],
	handles => {
		add_to_output => 'push',
		# join_output   => 'join', # want to return array(ref), not str
	},
);

has archive => (
    is         => 'ro',
    isa        => 'ArrayRef[LIMS::DB::RequestReportHistory]',
	lazy       => 1, # needed to avoid 'Can't use an undefined value as an ARRAY reference'
    default    => sub { [] },
	traits     => ['Array'],
	handles => {
		add_archive  => 'push',
		all_archives => 'elements',
	},
);

use Data::Dumper;

#-------------------------------------------------------------------------------
# accepts request.id:
sub get_lab_test_history {
	my ($self, $request_id) = @_;

    my $history =
        $self->model('History')->get_lab_test_history($request_id);

    return $history;
}

#-------------------------------------------------------------------------------
# accepts patient.id:
sub get_patient_history {
	my ($self, $patient_id) = @_;

    my $history =
        $self->model('History')->get_patient_history($patient_id);

    return $history;
}

#-------------------------------------------------------------------------------
# accepts patient.id:
sub get_demographic_history {
	my ($self, $patient_id) = @_;

    my $history =
        $self->model('History')->get_demographic_history($patient_id);

    return $history;
}

#-------------------------------------------------------------------------------
# accepts request.id:
sub get_request_history {
	my ($self, $request_id) = @_;

    my $history =
        $self->model('History')->get_request_history($request_id);

    return $history;
}

#-------------------------------------------------------------------------------
# accepts request.id:
sub get_diagnosis_history {
	my ($self, $request_id) = @_;

    my $history =
        $self->model('History')->get_diagnosis_history($request_id);

    return $history;
}

#-------------------------------------------------------------------------------
# accepts request oject:
sub get_deletion_history {
	my ($self, $request) = @_; # request object

    my $history = $self->model('History')->get_deletion_history($request);
    return $history;
}

#-------------------------------------------------------------------------------
sub history_log_event {
	my ($self, $args) = @_;

	my $request_id = $args->{request_id};
    my $profile    = $self->user_profile;    # warn Dumper $profile;
    my $config     = $self->cfg('settings'); # warn Dumper $config;
	my $event      = $args->{event};

	{ # don't log events from lab-staff:
        my $user_location = $profile->{user_location}->{location_name};
        my $central_labs  = $config->{central_labs} # not always configured
            || $config->{lab_name_abbreviation};
        my @central_labs = split ',', $central_labs; # warn Dumper \@central_labs;
		return 0 if grep $user_location eq $_, @central_labs;
        # don't log sysadmins (if we get this far - genomics uses cental_labs 'all_locations'):
        return 0 if $profile->{designation} eq 'sysadmin'; # only used in genomics
	}

	my %data = (
		request_id => $request_id,
		session    => $self->session,
		event      => $event,
	);

	my $rtn = $self->model('History')->do_log_event(\%data);
	warn $rtn if $rtn; # no need for user to see error
}

#-------------------------------------------------------------------------------
sub diff_report_changes {
    my ($self, $args) = @_;

	my $request_id = $args->{request_id};
	my $report_field = $args->{field};

	{ # previous entries from archive:
		my $archive	= $self->model('History')->get_report_history($args);

        return 0 unless @$archive; # no entries in request_report_history

		for (@$archive) { # $self->debug($_);
			$self->add_history($_->content);
			$self->add_archive($_);
		}
	}
	{ # current comment:
		my $report = $self->model('Report')->get_report($request_id);
		$self->add_history($report->$report_field);
	}

	my $count = $self->count_histories; # warn $count;
	my @histories = $self->all_histories;

	# send the first two entries (original comment & 1st modification) to
	# do_diff() and _get_original_report_details():
	{
		my $title = $self->_get_original_report_details($request_id);
		my $diffs = $self->do_diff(@histories[0,1]);

		$self->add_to_output({ title => $title, diff => $diffs });
	}

	if ($count > 2) { # we have more than one entry in comment_archive:
		# send rest to do_diff() and _get_revision_details():
		for my $i(1 .. $count - 2) {
			my $title = $self->_get_revision_details($i);
			my $diffs = $self->do_diff(@histories[$i, $i + 1]);

			$self->add_to_output({ title => $title, diff => $diffs });
		}
	}

	return $self->formatted_output;
}

#-------------------------------------------------------------------------------
sub _get_request_history {
	my ($self, $request_id) = @_;

	my $history = $self->model('History')->get_request_history($request_id);
	my %map = map { $_->action => $_ } @$history;
	return \%map;
}

#-------------------------------------------------------------------------------
sub _get_original_report_details {
	my ($self, $request_id) = @_;

    # report history:
	my $request_history_map = $self->_get_request_history($request_id);
	# get 1st entry from archive:
	my $archive_entry = $self->archive->[0];

	my $title = sprintf 'Original by %s %s on %s, modified by %s %s on %s',
		ucfirst $request_history_map->{reported}->user->first_name,
		ucfirst $request_history_map->{reported}->user->last_name,
		$request_history_map->{reported}->time->strftime('%d.%b.%Y @ %H:%M'),

		ucfirst $archive_entry->user->first_name,
		ucfirst $archive_entry->user->last_name,
		$archive_entry->time->strftime('%d.%b.%Y @ %H:%M');

	return $title;
}

#-------------------------------------------------------------------------------
sub _get_revision_details {
	my ($self, $archive_index) = @_;

	# get indexed entry from archive:
	my $archive_entry = $self->archive->[$archive_index];

	my $title = sprintf 'Further modified by %s %s on %s',
		ucfirst $archive_entry->user->first_name,
		ucfirst $archive_entry->user->last_name,
		$archive_entry->time->strftime('%d.%b.%Y @ %H:%M');

	return $title;
}

1;
