# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.

package Bugzilla::API::1_0::Resource::BugUserLastVisit;

use 5.14.0;
use strict;
use warnings;

use Bugzilla::API::1_0::Util;

use Bugzilla::Bug;
use Bugzilla::Error;
use Bugzilla::Constants;

use Moo;

extends 'Bugzilla::API::1_0::Resource';

##############
# Constants  #
##############

use constant READ_ONLY => qw(
  get
);

use constant PUBLIC_METHODS => qw(
  get
  update
);

sub REST_RESOURCES {
  use re '/a';
  return [
    # bug-id
    qr{^/bug_user_last_visit/(\d+)$},
    {
      GET => {
        method => 'get',
        params => sub {
          return {ids => [$_[0]]};
        },
      },
      POST => {
        method => 'update',
        params => sub {
          return {ids => [$_[0]]};
        },
      },
    },
  ];
}

############
# Methods  #
############

sub update {
  my ($self, $params) = validate(@_, 'ids');
  my $user = Bugzilla->user;
  my $dbh  = Bugzilla->dbh;

  $user->login(LOGIN_REQUIRED);

  my $ids = $params->{ids} // [];
  ThrowCodeError('param_required', {param => 'ids'}) unless @$ids;

  # Cache permissions for bugs. This highly reduces the number of calls to the
  # DB.  visible_bugs() is only able to handle bug IDs, so we have to skip
  # aliases.
  $user->visible_bugs([grep /^[0-9]+$/, @$ids]);

  $dbh->bz_start_transaction();
  my @results;
  my $last_visit_ts = $dbh->selectrow_array('SELECT NOW()');
  foreach my $bug_id (@$ids) {
    my $bug = Bugzilla::Bug->check({id => $bug_id, cache => 1});

    ThrowUserError('user_not_involved', {bug_id => $bug->id})
      unless $user->is_involved_in_bug($bug);

    $bug->update_user_last_visit($user, $last_visit_ts);

    push(@results,
      _bug_user_last_visit_to_hash($bug->bug_id, $last_visit_ts, $params));
  }
  $dbh->bz_commit_transaction();

  return \@results;
}

sub get {
  my ($self, $params) = validate(@_, 'ids');
  my $user = Bugzilla->user;
  my $ids  = $params->{ids};

  $user->login(LOGIN_REQUIRED);

  my @last_visits;
  if ($ids) {

    # Cache permissions for bugs. This highly reduces the number of calls to
    # the DB.  visible_bugs() is only able to handle bug IDs, so we have to
    # skip aliases.
    $user->visible_bugs([grep /^[0-9]+$/, @$ids]);

    my %last_visit
      = map { $_->bug_id => $_->last_visit_ts } @{$user->last_visited($ids)};
    @last_visits
      = map { _bug_user_last_visit_to_hash($_, $last_visit{$_}, $params) } @$ids;
  }
  else {
    @last_visits
      = map { _bug_user_last_visit_to_hash($_->bug_id, $_->last_visit_ts, $params) }
      @{$user->last_visited};
  }

  return \@last_visits;
}

sub _bug_user_last_visit_to_hash {
  my ($bug_id, $last_visit_ts, $params) = @_;

  my %result
    = (id => as_int($bug_id), last_visit_ts => as_datetime($last_visit_ts));

  return filter($params, \%result);
}

1;

__END__
=head1 NAME

Bugzilla::API::1_0::Resource::BugUserLastVisit - Find and Store the last time a
user visited a bug.

=head1 METHODS

=head2 update

=over

=item B<Description>

Update the last visit time for the specified bug and current user.

=item B<REST>

To add a single bug id:

    POST /rest/bug_user_last_visit/<bug-id>

Tp add one or more bug ids at once:

    POST /rest/bug_user_last_visit

The returned data format is the same as below.

=item B<Params>

=over

=item C<ids> (array) - One or more bug ids to add.

=back

=item B<Returns>

=over

=item C<array> - An array of hashes containing the following:

=over

=item C<id> - (int) The bug id.

=item C<last_visit_ts> - (string) The timestamp the user last visited the bug.

=back

=back

=back

=head2 get

=over

=item B<Description>

Get the last visited timestamp for one or more specified bug ids.

=item B<REST>

To return the last visited timestamp for a single bug id:

    GET /rest/bug_user_last_visit/<bug-id>

=item B<Params>

=over

=item C<ids> (integer) - One or more optional bug ids to get.

=back

=item B<Returns>

=over

=item C<array> - An array of hashes containing the following:

=over

=item C<id> - (int) The bug id.

=item C<last_visit_ts> - (string) The timestamp the user last visited the bug.

=back

=back

=back

=head1 B<Methods in need of POD>

=over

=item REST_RESOURCES

=back
