# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

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 framework import sorting
from mrproto 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])
      migrated_id = we.GetIssueMigratedID(
        issue_ref.project_name, issue_ref.local_id)
    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, migrated_id))

    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 sorted(results.items(), key=sorting.Python2Key)
      ]
    else:
      snapshot_counts = [
          issues_pb2.IssueSnapshotCount(dimension=key, count=result)
          for key, result in sorted(results.items(), key=sorting.Python2Key)
      ]
    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
