# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import copy
import logging

from google.protobuf import empty_pb2

import settings
from api import monorail_servicer
from api import converters
from api.api_proto import issue_objects_pb2
from api.api_proto import issues_pb2
from api.api_proto import issues_prpc_pb2
from businesslogic import work_env
from features import filterrules_helpers
from features import savedqueries_helpers
from framework import exceptions
from framework import framework_constants
from framework import framework_views
from framework import permissions
from proto import tracker_pb2
from search import searchpipeline
from tracker import field_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers


class IssuesServicer(monorail_servicer.MonorailServicer):
  """Handle API requests related to Issue objects.

  Each API request is implemented with a method as defined in the
  .proto file that does any request-specific validation, uses work_env
  to safely operate on business objects, and returns a response proto.
  """

  DESCRIPTION = issues_prpc_pb2.IssuesServiceDescription

  def _GetProjectIssueAndConfig(
      self, mc, issue_ref, use_cache=True, issue_required=True,
      view_deleted=False):
    """Get three objects that we need for most requests with an issue_ref."""
    issue = None
    with work_env.WorkEnv(mc, self.services, phase='getting P, I, C') as we:
      project = we.GetProjectByName(
          issue_ref.project_name, use_cache=use_cache)
      mc.LookupLoggedInUserPerms(project)
      config = we.GetProjectConfig(project.project_id, use_cache=use_cache)
      if issue_required or issue_ref.local_id:
        try:
          issue = we.GetIssueByLocalID(
              project.project_id, issue_ref.local_id, use_cache=use_cache,
              allow_viewing_deleted=view_deleted)
        except exceptions.NoSuchIssueException as e:
          issue = None
          if issue_required:
            raise e
    return project, issue, config

  def _GetProjectIssueIDsAndConfig(
      self, mc, issue_refs, use_cache=True):
    """Get info from a single project for repeated issue_refs requests."""
    project_names = set()
    local_ids = []
    for issue_ref in issue_refs:
      if not issue_ref.local_id:
        raise exceptions.InputException('Param `local_id` required.')
      local_ids.append(issue_ref.local_id)
      if issue_ref.project_name:
        project_names.add(issue_ref.project_name)

    if not project_names:
      raise exceptions.InputException('Param `project_name` required.')
    if len(project_names) != 1:
      raise exceptions.InputException(
          'This method does not support cross-project issue_refs.')
    project_name = project_names.pop()
    with work_env.WorkEnv(mc, self.services, phase='getting P, I ids, C') as we:
      project = we.GetProjectByName(project_name, use_cache=use_cache)
      mc.LookupLoggedInUserPerms(project)
      config = we.GetProjectConfig(project.project_id, use_cache=use_cache)
      project_local_id_pairs = [(project.project_id, local_id)
                                for local_id in local_ids]
    issue_ids, _misses = self.services.issue.LookupIssueIDs(
        mc.cnxn, project_local_id_pairs)
    return project, issue_ids, config

  @monorail_servicer.PRPCMethod
  def CreateIssue(self, _mc, request):
    response = issue_objects_pb2.Issue()
    response.CopyFrom(request.issue)
    return response

  @monorail_servicer.PRPCMethod
  def GetIssue(self, mc, request):
    """Return the specified issue in a response proto."""
    issue_ref = request.issue_ref
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, issue_ref, view_deleted=True, issue_required=False)

    # Code for getting where a moved issue was moved to.
    if issue is None:
      moved_to_ref = self.services.issue.GetCurrentLocationOfMovedIssue(
          mc.cnxn, project.project_id, issue_ref.local_id)
      moved_to_project_id, moved_to_id = moved_to_ref
      moved_to_project_name = None

      if moved_to_project_id is not None:
        with work_env.WorkEnv(mc, self.services) as we:
          moved_to_project = we.GetProject(moved_to_project_id)
          moved_to_project_name = moved_to_project.project_name
        return issues_pb2.IssueResponse(moved_to_ref=converters.ConvertIssueRef(
            (moved_to_project_name, moved_to_id)))

      raise exceptions.NoSuchIssueException()

    if issue.deleted:
      return issues_pb2.IssueResponse(
          issue=issue_objects_pb2.Issue(is_deleted=True))

    with work_env.WorkEnv(mc, self.services) as we:
      related_refs = we.GetRelatedIssueRefs([issue])

    with mc.profiler.Phase('making user views'):
      users_involved_in_issue = tracker_bizobj.UsersInvolvedInIssues([issue])
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved_in_issue)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)

    with mc.profiler.Phase('converting to response objects'):
      response = issues_pb2.IssueResponse()
      response.issue.CopyFrom(converters.ConvertIssue(
          issue, users_by_id, related_refs, config))

    return response

  @monorail_servicer.PRPCMethod
  def ListIssues(self, mc, request):
    """Return the list of issues for projects that satisfy the given query."""
    use_cached_searches = not settings.local_mode
    can = request.canned_query or 1
    with work_env.WorkEnv(mc, self.services) as we:
      start, max_items = converters.IngestPagination(request.pagination)
      pipeline = we.ListIssues(
          request.query, request.project_names, mc.auth.user_id, max_items,
          start, can, request.group_by_spec, request.sort_spec,
          use_cached_searches)
    with mc.profiler.Phase('reveal emails to members'):
      projects = self.services.project.GetProjectsByName(
          mc.cnxn, request.project_names)
      for _, p in projects.items():
        framework_views.RevealAllEmailsToMembers(
            mc.cnxn, self.services, mc.auth, pipeline.users_by_id, p)

    converted_results = []
    with work_env.WorkEnv(mc, self.services) as we:
      for issue in (pipeline.visible_results or []):
        related_refs = we.GetRelatedIssueRefs([issue])
        converted_results.append(
            converters.ConvertIssue(issue, pipeline.users_by_id, related_refs,
                                    pipeline.harmonized_config))
    total_results = 0
    if hasattr(pipeline.pagination, 'total_count'):
      total_results = pipeline.pagination.total_count
    return issues_pb2.ListIssuesResponse(
        issues=converted_results, total_results=total_results)


  @monorail_servicer.PRPCMethod
  def ListReferencedIssues(self, mc, request):
    """Return the specified issues in a response proto."""
    if not request.issue_refs:
      return issues_pb2.ListReferencedIssuesResponse()

    for issue_ref in request.issue_refs:
      if not issue_ref.project_name:
        raise exceptions.InputException('Param `project_name` required.')
      if not issue_ref.local_id:
        raise exceptions.InputException('Param `local_id` required.')

    default_project_name = request.issue_refs[0].project_name
    ref_tuples = [
        (ref.project_name, ref.local_id) for ref in request.issue_refs]
    with work_env.WorkEnv(mc, self.services) as we:
      open_issues, closed_issues = we.ListReferencedIssues(
          ref_tuples, default_project_name)
      all_issues = open_issues + closed_issues
      all_project_ids = [issue.project_id for issue in all_issues]
      related_refs = we.GetRelatedIssueRefs(all_issues)
      configs = we.GetProjectConfigs(all_project_ids)

    with mc.profiler.Phase('making user views'):
      users_involved = tracker_bizobj.UsersInvolvedInIssues(all_issues)
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id)

    with mc.profiler.Phase('converting to response objects'):
      converted_open_issues = [
          converters.ConvertIssue(
              issue, users_by_id, related_refs, configs[issue.project_id])
          for issue in open_issues]
      converted_closed_issues = [
          converters.ConvertIssue(
              issue, users_by_id, related_refs, configs[issue.project_id])
          for issue in closed_issues]
      response = issues_pb2.ListReferencedIssuesResponse(
          open_refs=converted_open_issues, closed_refs=converted_closed_issues)

    return response

  @monorail_servicer.PRPCMethod
  def ListApplicableFieldDefs(self, mc, request):
    """Returns specified issues' applicable field refs in a response proto."""
    if not request.issue_refs:
      return issues_pb2.ListApplicableFieldDefsResponse()

    _project, issue_ids, config = self._GetProjectIssueIDsAndConfig(
        mc, request.issue_refs)
    with work_env.WorkEnv(mc, self.services) as we:
      issues_dict = we.GetIssuesDict(issue_ids)
      fds = field_helpers.ListApplicableFieldDefs(issues_dict.values(), config)

    users_by_id = {}
    with mc.profiler.Phase('converting to response objects'):
      users_involved = tracker_bizobj.UsersInvolvedInConfig(config)
      users_by_id.update(framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved))
      field_defs = [
          converters.ConvertFieldDef(fd, [], users_by_id, config, True)
          for fd in fds]

    return issues_pb2.ListApplicableFieldDefsResponse(field_defs=field_defs)

  @monorail_servicer.PRPCMethod
  def UpdateIssue(self, mc, request):
    """Apply a delta and comment to the specified issue, then return it."""
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      if request.HasField('delta'):
        delta = converters.IngestIssueDelta(
            mc.cnxn, self.services, request.delta, config, issue.phases)
      else:
        delta = tracker_pb2.IssueDelta()  # No changes specified.
      attachments = converters.IngestAttachmentUploads(request.uploads)
      we.UpdateIssue(
          issue, delta, request.comment_content, send_email=request.send_email,
          attachments=attachments, is_description=request.is_description,
          kept_attachments=list(request.kept_attachments))
      related_refs = we.GetRelatedIssueRefs([issue])

    with mc.profiler.Phase('making user views'):
      users_involved_in_issue = tracker_bizobj.UsersInvolvedInIssues([issue])
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved_in_issue)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)

    with mc.profiler.Phase('converting to response objects'):
      response = issues_pb2.IssueResponse()
      response.issue.CopyFrom(converters.ConvertIssue(
          issue, users_by_id, related_refs, config))

    return response

  @monorail_servicer.PRPCMethod
  def StarIssue(self, mc, request):
    """Star (or unstar) the specified issue."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      we.StarIssue(issue, request.starred)
      # Reload the issue to get the new star count.
      issue = we.GetIssue(issue.issue_id)

    with mc.profiler.Phase('converting to response objects'):
      response = issues_pb2.StarIssueResponse()
      response.star_count = issue.star_count

    return response

  @monorail_servicer.PRPCMethod
  def IsIssueStarred(self, mc, request):
    """Respond true if the signed-in user has starred the specified issue."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      is_starred = we.IsIssueStarred(issue)

    with mc.profiler.Phase('converting to response objects'):
      response = issues_pb2.IsIssueStarredResponse()
      response.is_starred = is_starred

    return response

  @monorail_servicer.PRPCMethod
  def ListStarredIssues(self, mc, _request):
    """Return a list of issue ids that the signed-in user has starred."""
    with work_env.WorkEnv(mc, self.services) as we:
      starred_issues = we.ListStarredIssueIDs()
      starred_issues_dict = we.GetIssueRefs(starred_issues)

    with mc.profiler.Phase('converting to response objects'):
      converted_starred_issue_refs = converters.ConvertIssueRefs(
        starred_issues, starred_issues_dict)
      response = issues_pb2.ListStarredIssuesResponse(
        starred_issue_refs=converted_starred_issue_refs)

    return response

  @monorail_servicer.PRPCMethod
  def ListComments(self, mc, request):
    """Return comments on the specified issue in a response proto."""
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref)
    with work_env.WorkEnv(mc, self.services) as we:
      comments = we.ListIssueComments(issue)
      _, comment_reporters = we.LookupIssueFlaggers(issue)

    with mc.profiler.Phase('making user views'):
      users_involved_in_comments = tracker_bizobj.UsersInvolvedInCommentList(
         comments)
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved_in_comments)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)

    with mc.profiler.Phase('converting to response objects'):
      issue_perms = permissions.UpdateIssuePermissions(
          mc.perms, project, issue, mc.auth.effective_ids, config=config)
      converted_comments = converters.ConvertCommentList(
          issue, comments, config, users_by_id, comment_reporters,
          mc.auth.user_id, issue_perms)
      response = issues_pb2.ListCommentsResponse(comments=converted_comments)

    return response

  @monorail_servicer.PRPCMethod
  def ListActivities(self, mc, request):
    """Return issue activities by a specified user in a response proto."""
    converted_user = converters.IngestUserRef(mc.cnxn, request.user_ref,
        self.services.user)
    user = self.services.user.GetUser(mc.cnxn, converted_user)
    comments = self.services.issue.GetIssueActivity(
        mc.cnxn, user_ids={request.user_ref.user_id})
    issues = self.services.issue.GetIssues(
        mc.cnxn, {c.issue_id for c in comments})
    project_dict = tracker_helpers.GetAllIssueProjects(
        mc.cnxn, issues, self.services.project)
    config_dict = self.services.config.GetProjectConfigs(
        mc.cnxn, list(project_dict.keys()))
    allowed_issues = tracker_helpers.FilterOutNonViewableIssues(
        mc.auth.effective_ids, user, project_dict,
        config_dict, issues)
    issue_dict = {issue.issue_id: issue for issue in allowed_issues}
    comments = [
        c for c in comments if c.issue_id in issue_dict]

    users_by_id = framework_views.MakeAllUserViews(
        mc.cnxn, self.services.user, [request.user_ref.user_id],
        tracker_bizobj.UsersInvolvedInCommentList(comments))
    for project in project_dict.values():
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)

    issues_by_project = {}
    for issue in allowed_issues:
      issues_by_project.setdefault(issue.project_id, []).append(issue)

    # A dictionary {issue_id: perms} of the PermissionSet for the current user
    # on each of the issues.
    issue_perms_dict = {}
    # A dictionary {comment_id: [reporter_id]} of users who have reported the
    # comment as spam.
    comment_reporters = {}
    for project_id, project_issues in issues_by_project.items():
      mc.LookupLoggedInUserPerms(project_dict[project_id])
      issue_perms_dict.update({
          issue.issue_id: permissions.UpdateIssuePermissions(
              mc.perms, project_dict[issue.project_id], issue,
              mc.auth.effective_ids, config=config_dict[issue.project_id])
          for issue in project_issues})

      with work_env.WorkEnv(mc, self.services) as we:
        project_issue_reporters = we.LookupIssuesFlaggers(project_issues)
        for _, issue_comment_reporters in project_issue_reporters.values():
          comment_reporters.update(issue_comment_reporters)

    with mc.profiler.Phase('converting to response objects'):
      converted_comments = []
      for c in comments:
        issue = issue_dict.get(c.issue_id)
        issue_perms = issue_perms_dict.get(c.issue_id)
        result = converters.ConvertComment(
            issue, c,
            config_dict.get(issue.project_id),
            users_by_id,
            comment_reporters.get(c.id, []),
            {c.id: 1} if c.is_description else {},
            mc.auth.user_id, issue_perms)
        converted_comments.append(result)
      converted_issues = [issue_objects_pb2.IssueSummary(
          project_name=issue.project_name, local_id=issue.local_id,
          summary=issue.summary) for issue in allowed_issues]
      response = issues_pb2.ListActivitiesResponse(
          comments=converted_comments, issue_summaries=converted_issues)

    return response

  @monorail_servicer.PRPCMethod
  def DeleteComment(self, mc, request):
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)
    with work_env.WorkEnv(mc, self.services) as we:
      all_comments = we.ListIssueComments(issue)
      try:
        comment = all_comments[request.sequence_num]
      except IndexError:
        raise exceptions.NoSuchCommentException()
      we.DeleteComment(issue, comment, request.delete)

    return empty_pb2.Empty()

  @monorail_servicer.PRPCMethod
  def BulkUpdateApprovals(self, mc, request):
    """Update multiple issues' approval and return the updated issue_refs."""
    if not request.issue_refs:
      raise exceptions.InputException('Param `issue_refs` empty.')

    project, issue_ids, config = self._GetProjectIssueIDsAndConfig(
        mc, request.issue_refs)

    approval_fd = tracker_bizobj.FindFieldDef(
        request.field_ref.field_name, config)
    if not approval_fd:
      raise exceptions.NoSuchFieldDefException()
    if request.HasField('approval_delta'):
      approval_delta = converters.IngestApprovalDelta(
          mc.cnxn, self.services.user, request.approval_delta,
          mc.auth.user_id, config)
    else:
      approval_delta = tracker_pb2.ApprovalDelta()
    # No bulk adding approval attachments for now.

    with work_env.WorkEnv(mc, self.services, phase='updating approvals') as we:
      updated_issue_ids = we.BulkUpdateIssueApprovals(
          issue_ids, approval_fd.field_id, project, approval_delta,
          request.comment_content, send_email=request.send_email)
      with mc.profiler.Phase('converting to response objects'):
        issue_ref_pairs = we.GetIssueRefs(updated_issue_ids)
        issue_refs = [converters.ConvertIssueRef(pair)
                      for pair in issue_ref_pairs.values()]
        response = issues_pb2.BulkUpdateApprovalsResponse(issue_refs=issue_refs)

    return response

  @monorail_servicer.PRPCMethod
  def UpdateApproval(self, mc, request):
    """Update and return an approval in a response proto."""
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    approval_fd = tracker_bizobj.FindFieldDef(
        request.field_ref.field_name, config)
    if not approval_fd:
      raise exceptions.NoSuchFieldDefException()
    if request.HasField('approval_delta'):
      approval_delta = converters.IngestApprovalDelta(
          mc.cnxn, self.services.user, request.approval_delta,
          mc.auth.user_id, config)
    else:
      approval_delta = tracker_pb2.ApprovalDelta()
    attachments = converters.IngestAttachmentUploads(request.uploads)

    with work_env.WorkEnv(mc, self.services) as we:
      av, _comment, _issue = we.UpdateIssueApproval(
          issue.issue_id,
          approval_fd.field_id,
          approval_delta,
          request.comment_content,
          request.is_description,
          attachments=attachments,
          send_email=request.send_email,
          kept_attachments=list(request.kept_attachments))

    with mc.profiler.Phase('converting to response objects'):
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, av.approver_ids, [av.setter_id])
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)
      response = issues_pb2.UpdateApprovalResponse()
      response.approval.CopyFrom(converters.ConvertApproval(
          av, users_by_id, config))

    return response

  @monorail_servicer.PRPCMethod
  def ConvertIssueApprovalsTemplate(self, mc, request):
    """Update an issue's existing approvals structure to match the one of the
       given template."""

    if not request.issue_ref.local_id or not request.issue_ref.project_name:
      raise exceptions.InputException('Param `issue_ref.local_id` empty')
    if not request.template_name:
      raise exceptions.InputException('Param `template_name` empty')

    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      we.ConvertIssueApprovalsTemplate(
          config, issue, request.template_name, request.comment_content,
          send_email=request.send_email)
      related_refs = we.GetRelatedIssueRefs([issue])

    with mc.profiler.Phase('making user views'):
      users_involved_in_issue = tracker_bizobj.UsersInvolvedInIssues([issue])
      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, users_involved_in_issue)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, users_by_id, project)

    with mc.profiler.Phase('converting to response objects'):
      response = issues_pb2.ConvertIssueApprovalsTemplateResponse()
      response.issue.CopyFrom(converters.ConvertIssue(
          issue, users_by_id, related_refs, config))
    return response

  @monorail_servicer.PRPCMethod
  def IssueSnapshot(self, mc, request):
    """Fetch IssueSnapshot counts for charting."""
    warnings = []

    if not request.timestamp:
      raise exceptions.InputException('Param `timestamp` required.')

    if not request.project_name and not request.hotlist_id:
      raise exceptions.InputException('Params `project_name` or `hotlist_id` '
          'required.')

    if request.group_by == 'label' and not request.label_prefix:
      raise exceptions.InputException('Param `label_prefix` required.')

    if request.canned_query:
      canned_query = savedqueries_helpers.SavedQueryIDToCond(
          mc.cnxn, self.services.features, request.canned_query)
      # TODO(jrobbins): support linked accounts me_user_ids.
      canned_query, warnings = searchpipeline.ReplaceKeywordsWithUserIDs(
          [mc.auth.user_id], canned_query)
    else:
      canned_query = None

    if request.query:
      query, warnings = searchpipeline.ReplaceKeywordsWithUserIDs(
          [mc.auth.user_id], request.query)
    else:
      query = None

    with work_env.WorkEnv(mc, self.services) as we:
      try:
        project = we.GetProjectByName(request.project_name)
      except exceptions.NoSuchProjectException:
        project = None

      if request.hotlist_id:
        hotlist = we.GetHotlist(request.hotlist_id)
      else:
        hotlist = None

      results, unsupported_fields, limit_reached = we.SnapshotCountsQuery(
          project, request.timestamp, request.group_by,
          label_prefix=request.label_prefix, query=query,
          canned_query=canned_query, hotlist=hotlist)
    if request.group_by == 'owner':
      # Map user ids to emails.
      snapshot_counts = [
        issues_pb2.IssueSnapshotCount(
          dimension=self.services.user.GetUser(mc.cnxn, key).email,
          count=result) for key, result in results.iteritems()
      ]
    else:
      snapshot_counts = [
        issues_pb2.IssueSnapshotCount(dimension=key, count=result)
          for key, result in results.items()
      ]
    response = issues_pb2.IssueSnapshotResponse()
    response.snapshot_count.extend(snapshot_counts)
    response.unsupported_field.extend(unsupported_fields)
    response.unsupported_field.extend(warnings)
    response.search_limit_reached = limit_reached
    return response

  @monorail_servicer.PRPCMethod
  def PresubmitIssue(self, mc, request):
    """Provide the UI with warnings and suggestions."""
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, issue_required=False)

    with mc.profiler.Phase('making user views'):
      try:
        proposed_owner_id = converters.IngestUserRef(
            mc.cnxn, request.issue_delta.owner_ref, self.services.user)
      except exceptions.NoSuchUserException:
        proposed_owner_id = 0

      users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, [proposed_owner_id])
      proposed_owner_view = users_by_id[proposed_owner_id]

    with mc.profiler.Phase('Applying IssueDelta'):
      if issue:
        proposed_issue = copy.deepcopy(issue)
      else:
        proposed_issue = tracker_pb2.Issue(
          owner_id=framework_constants.NO_USER_SPECIFIED,
          project_id=config.project_id)
      issue_delta = converters.IngestIssueDelta(
          mc.cnxn, self.services, request.issue_delta, config, None,
          ignore_missing_objects=True)
      tracker_bizobj.ApplyIssueDelta(
          mc.cnxn, self.services.issue, proposed_issue, issue_delta, config)

    with mc.profiler.Phase('applying rules'):
      _, traces = filterrules_helpers.ApplyFilterRules(
          mc.cnxn, self.services, proposed_issue, config)
      logging.info('proposed_issue is now: %r', proposed_issue)
      logging.info('traces are: %r', traces)

    with mc.profiler.Phase('making derived user views'):
      derived_users_by_id = framework_views.MakeAllUserViews(
          mc.cnxn, self.services.user, [proposed_issue.derived_owner_id],
          proposed_issue.derived_cc_ids)
      framework_views.RevealAllEmailsToMembers(
          mc.cnxn, self.services, mc.auth, derived_users_by_id, project)

    with mc.profiler.Phase('pair derived values with rule explanations'):
      (derived_labels, derived_owners, derived_ccs, warnings, errors) = (
          tracker_helpers.PairDerivedValuesWithRuleExplanations(
              proposed_issue, traces, derived_users_by_id))

    result = issues_pb2.PresubmitIssueResponse(
        owner_availability=proposed_owner_view.avail_message_short,
        owner_availability_state=proposed_owner_view.avail_state,
        derived_labels=converters.ConvertValueAndWhyList(derived_labels),
        derived_owners=converters.ConvertValueAndWhyList(derived_owners),
        derived_ccs=converters.ConvertValueAndWhyList(derived_ccs),
        warnings=converters.ConvertValueAndWhyList(warnings),
        errors=converters.ConvertValueAndWhyList(errors))
    return result

  @monorail_servicer.PRPCMethod
  def RerankBlockedOnIssues(self, mc, request):
    """Rerank the blocked on issues for the given issue ref."""
    moved_issue_id, target_issue_id = converters.IngestIssueRefs(
        mc.cnxn, [request.moved_ref, request.target_ref], self.services)
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref)

    with work_env.WorkEnv(mc, self.services) as we:
      we.RerankBlockedOnIssues(
          issue, moved_issue_id, target_issue_id, request.split_above)

    with work_env.WorkEnv(mc, self.services) as we:
      issue = we.GetIssue(issue.issue_id)
      related_refs = we.GetRelatedIssueRefs([issue])

    with mc.profiler.Phase('converting to response objects'):
      converted_issue_refs = converters.ConvertIssueRefs(
          issue.blocked_on_iids, related_refs)
      result = issues_pb2.RerankBlockedOnIssuesResponse(
          blocked_on_issue_refs=converted_issue_refs)

    return result

  @monorail_servicer.PRPCMethod
  def DeleteIssue(self, mc, request):
    """Mark or unmark the given issue as deleted."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, view_deleted=True)

    with work_env.WorkEnv(mc, self.services) as we:
      we.DeleteIssue(issue, request.delete)

    result = issues_pb2.DeleteIssueResponse()
    return result

  @monorail_servicer.PRPCMethod
  def DeleteIssueComment(self, mc, request):
    """Mark or unmark the given comment as deleted."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      comments = we.ListIssueComments(issue)
      if request.sequence_num >= len(comments):
        raise exceptions.InputException('Invalid sequence number.')
      we.DeleteComment(issue, comments[request.sequence_num], request.delete)

    result = issues_pb2.DeleteIssueCommentResponse()
    return result

  @monorail_servicer.PRPCMethod
  def DeleteAttachment(self, mc, request):
    """Mark or unmark the given attachment as deleted."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      comments = we.ListIssueComments(issue)
      if request.sequence_num >= len(comments):
        raise exceptions.InputException('Invalid sequence number.')
      we.DeleteAttachment(
          issue, comments[request.sequence_num], request.attachment_id,
          request.delete)

    result = issues_pb2.DeleteAttachmentResponse()
    return result

  @monorail_servicer.PRPCMethod
  def FlagIssues(self, mc, request):
    """Flag or unflag the given issues as spam."""
    if not request.issue_refs:
      raise exceptions.InputException('Param `issue_refs` empty.')

    _project, issue_ids, _config = self._GetProjectIssueIDsAndConfig(
        mc, request.issue_refs)
    with work_env.WorkEnv(mc, self.services) as we:
      issues_by_id = we.GetIssuesDict(issue_ids, use_cache=False)
      we.FlagIssues(list(issues_by_id.values()), request.flag)

    result = issues_pb2.FlagIssuesResponse()
    return result

  @monorail_servicer.PRPCMethod
  def FlagComment(self, mc, request):
    """Flag or unflag the given comment as spam."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      comments = we.ListIssueComments(issue)
      if request.sequence_num >= len(comments):
        raise exceptions.InputException('Invalid sequence number.')
      we.FlagComment(issue, comments[request.sequence_num], request.flag)

    result = issues_pb2.FlagCommentResponse()
    return result

  @monorail_servicer.PRPCMethod
  def ListIssuePermissions(self, mc, request):
    """List the permissions for the current user in the given issue."""
    project, issue, config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False, view_deleted=True)

    perms = permissions.UpdateIssuePermissions(
        mc.perms, project, issue, mc.auth.effective_ids, config=config)

    return issues_pb2.ListIssuePermissionsResponse(
        permissions=sorted(perms.perm_names))

  @monorail_servicer.PRPCMethod
  def MoveIssue(self, mc, request):
    """Move an issue to another project."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      target_project = we.GetProjectByName(request.target_project_name)
      moved_issue = we.MoveIssue(issue, target_project)

    result = issues_pb2.MoveIssueResponse(
        new_issue_ref=converters.ConvertIssueRef(
            (moved_issue.project_name, moved_issue.local_id)))
    return result

  @monorail_servicer.PRPCMethod
  def CopyIssue(self, mc, request):
    """Copy an issue."""
    _project, issue, _config = self._GetProjectIssueAndConfig(
        mc, request.issue_ref, use_cache=False)

    with work_env.WorkEnv(mc, self.services) as we:
      target_project = we.GetProjectByName(request.target_project_name)
      copied_issue = we.CopyIssue(issue, target_project)

    result = issues_pb2.CopyIssueResponse(
        new_issue_ref=converters.ConvertIssueRef(
            (copied_issue.project_name, copied_issue.local_id)))
    return result
