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

"""Helper functions and classes used by the Monorail Issue Tracker pages.

This module has functions that are reused in multiple servlets or
other modules.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import itertools
import logging
import re
import time
from six.moves import urllib

from google.appengine.api import app_identity

from six import string_types

import settings

from features import federated
from framework import authdata
from framework import exceptions
from framework import filecontent
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import permissions
from framework import sorting
from framework import template_helpers
from framework import urls
from project import project_helpers
from mrproto import tracker_pb2
from services import client_config_svc
from tracker import field_helpers
from tracker import tracker_bizobj
from tracker import tracker_constants


# HTML input field names for blocked on and blocking issue refs.
BLOCKED_ON = 'blocked_on'
BLOCKING = 'blocking'

# This string is used in HTML form element names to identify custom fields.
# E.g., a value for a custom field with field_id 12 would be specified in
# an HTML form element with name="custom_12".
_CUSTOM_FIELD_NAME_PREFIX = 'custom_'

# When the attachment quota gets within 1MB of the limit, stop offering
# users the option to attach files.
_SOFT_QUOTA_LEEWAY = 1024 * 1024

# Accessors for sorting built-in fields.
SORTABLE_FIELDS = {
    'project': lambda issue: issue.project_name,
    'id': lambda issue: issue.local_id,
    'owner': tracker_bizobj.GetOwnerId,  # And postprocessor
    'reporter': lambda issue: issue.reporter_id,  # And postprocessor
    'component': lambda issue: issue.component_ids,
    'cc': tracker_bizobj.GetCcIds,  # And postprocessor
    'summary': lambda issue: issue.summary.lower(),
    'stars': lambda issue: issue.star_count,
    'attachments': lambda issue: issue.attachment_count,
    'opened': lambda issue: issue.opened_timestamp,
    'closed': lambda issue: issue.closed_timestamp,
    'modified': lambda issue: issue.modified_timestamp,
    'status': tracker_bizobj.GetStatus,
    'blocked': lambda issue: bool(issue.blocked_on_iids),
    'blockedon': lambda issue: issue.blocked_on_iids or sorting.MAX_STRING,
    'blocking': lambda issue: issue.blocking_iids or sorting.MAX_STRING,
    'mergedinto': lambda issue: issue.merged_into or sorting.MAX_STRING,
    'ownermodified': lambda issue: issue.owner_modified_timestamp,
    'statusmodified': lambda issue: issue.status_modified_timestamp,
    'componentmodified': lambda issue: issue.component_modified_timestamp,
    'ownerlastvisit': tracker_bizobj.GetOwnerId,  # And postprocessor
    }

# Some fields take a user ID from the issue and then use that to index
# into a dictionary of user views, and then get a field of the user view
# as the value to sort key.
SORTABLE_FIELDS_POSTPROCESSORS = {
    'owner': lambda user_view: user_view.email,
    'reporter': lambda user_view: user_view.email,
    'cc': lambda user_view: user_view.email,
    'ownerlastvisit': lambda user_view: -user_view.user.last_visit_timestamp,
    }

# Here are some restriction labels to help people do the most common things
# that they might want to do with restrictions.
_FREQUENT_ISSUE_RESTRICTIONS = [
    (permissions.VIEW, permissions.EDIT_ISSUE,
     'Only users who can edit the issue may access it'),
    (permissions.ADD_ISSUE_COMMENT, permissions.EDIT_ISSUE,
     'Only users who can edit the issue may add comments'),
    ]

# These issue restrictions should be offered as examples whenever the project
# does not have any custom permissions in use already.
_EXAMPLE_ISSUE_RESTRICTIONS = [
    (permissions.VIEW, 'CoreTeam',
     'Custom permission CoreTeam is needed to access'),
    ]

# Namedtuples that hold data parsed from post_data.
ParsedComponents = collections.namedtuple(
    'ParsedComponents', 'entered_str, paths, paths_remove')
ParsedFields = collections.namedtuple(
    'ParsedFields',
    'vals, vals_remove, fields_clear, '
    'phase_vals, phase_vals_remove')
ParsedUsers = collections.namedtuple(
    'ParsedUsers', 'owner_username, owner_id, cc_usernames, '
    'cc_usernames_remove, cc_ids, cc_ids_remove')
ParsedBlockers = collections.namedtuple(
    'ParsedBlockers', 'entered_str, iids, dangling_refs, '
    'federated_ref_strings')
ParsedHotlistRef = collections.namedtuple(
    'ParsedHotlistRef', 'user_email, hotlist_name')
ParsedHotlists = collections.namedtuple(
    'ParsedHotlists', 'entered_str, hotlist_refs')
ParsedIssue = collections.namedtuple(
    'ParsedIssue', 'summary, comment, is_description, status, users, labels, '
    'labels_remove, components, fields, template_name, attachments, '
    'kept_attachments, blocked_on, blocking, hotlists')


def ParseIssueRequest(cnxn, post_data, services, errors, default_project_name):
  """Parse all the possible arguments out of the request.

  Args:
    cnxn: connection to SQL database.
    post_data: HTML form information.
    services: Connections to persistence layer.
    errors: object to accumulate validation error info.
    default_project_name: name of the project that contains the issue.

  Returns:
    A namedtuple with all parsed information.  User IDs are looked up, but
    also the strings are returned to allow bouncing the user back to correct
    any errors.
  """
  summary = post_data.get('summary', '')
  comment = post_data.get('comment', '')
  is_description = bool(post_data.get('description', ''))
  status = post_data.get('status', '')
  template_name = urllib.parse.unquote_plus(post_data.get('template_name', ''))
  component_str = post_data.get('components', '')
  label_strs = post_data.getlist('label')

  if is_description:
    tmpl_txt = post_data.get('tmpl_txt', '')
    comment = MarkupDescriptionOnInput(comment, tmpl_txt)

  comp_paths, comp_paths_remove = _ClassifyPlusMinusItems(
      re.split(r'[,;\s]+', component_str))
  parsed_components = ParsedComponents(
      component_str, comp_paths, comp_paths_remove)
  labels, labels_remove = _ClassifyPlusMinusItems(label_strs)
  parsed_fields = _ParseIssueRequestFields(post_data)
  # TODO(jrobbins): change from numbered fields to a multi-valued field.
  attachments = _ParseIssueRequestAttachments(post_data)
  kept_attachments = _ParseIssueRequestKeptAttachments(post_data)
  parsed_users = _ParseIssueRequestUsers(cnxn, post_data, services)
  parsed_blocked_on = _ParseBlockers(
      cnxn, post_data, services, errors, default_project_name, BLOCKED_ON)
  parsed_blocking = _ParseBlockers(
      cnxn, post_data, services, errors, default_project_name, BLOCKING)
  parsed_hotlists = _ParseHotlists(post_data)

  parsed_issue = ParsedIssue(
      summary, comment, is_description, status, parsed_users, labels,
      labels_remove, parsed_components, parsed_fields, template_name,
      attachments, kept_attachments, parsed_blocked_on, parsed_blocking,
      parsed_hotlists)
  return parsed_issue


def MarkupDescriptionOnInput(content, tmpl_text):
  """Return HTML for the content of an issue description or comment.

  Args:
    content: the text sumbitted by the user, any user-entered markup
             has already been escaped.
    tmpl_text: the initial text that was put into the textarea.

  Returns:
    The description content text with template lines highlighted.
  """
  tmpl_lines = tmpl_text.split('\n')
  tmpl_lines = [pl.strip() for pl in tmpl_lines if pl.strip()]

  entered_lines = content.split('\n')
  marked_lines = [_MarkupDescriptionLineOnInput(line, tmpl_lines)
                  for line in entered_lines]
  return '\n'.join(marked_lines)


def _MarkupDescriptionLineOnInput(line, tmpl_lines):
  """Markup one line of an issue description that was just entered.

  Args:
    line: string containing one line of the user-entered comment.
    tmpl_lines: list of strings for the text of the template lines.

  Returns:
    The same user-entered line, or that line highlighted to
    indicate that it came from the issue template.
  """
  for tmpl_line in tmpl_lines:
    if line.startswith(tmpl_line):
      return '<b>' + tmpl_line + '</b>' + line[len(tmpl_line):]

  return line


def _ClassifyPlusMinusItems(add_remove_list):
  """Classify the given plus-or-minus items into add and remove lists."""
  add_remove_set = {s.strip() for s in add_remove_list}
  add_strs = [s for s in add_remove_set if s and not s.startswith('-')]
  remove_strs = [s[1:] for s in add_remove_set if s[1:] and s.startswith('-')]
  return add_strs, remove_strs


def _ParseHotlists(post_data):
  entered_str = post_data.get('hotlists', '').strip()
  hotlist_refs = []
  for ref_str in re.split(r'[,;\s]+', entered_str):
    if not ref_str:
      continue
    if ':' in ref_str:
      if ref_str.split(':')[0]:
        # E-mail isn't empty; full reference.
        hotlist_refs.append(ParsedHotlistRef(*ref_str.split(':', 1)))
      else:
        # Short reference.
        hotlist_refs.append(ParsedHotlistRef(None, ref_str.split(':', 1)[1]))
    else:
      # Short reference
      hotlist_refs.append(ParsedHotlistRef(None, ref_str))
  parsed_hotlists = ParsedHotlists(entered_str, hotlist_refs)
  return parsed_hotlists


def _ParseIssueRequestFields(post_data):
  """Iterate over post_data and return custom field values found in it."""
  field_val_strs = {}
  field_val_strs_remove = {}
  phase_field_val_strs = collections.defaultdict(dict)
  phase_field_val_strs_remove = collections.defaultdict(dict)
  for key in post_data.keys():
    if key.startswith(_CUSTOM_FIELD_NAME_PREFIX):
      val_strs = [v for v in post_data.getlist(key) if v]
      if val_strs:
        try:
          field_id = int(key[len(_CUSTOM_FIELD_NAME_PREFIX):])
          phase_name = None
        except ValueError:  # key must be in format <field_id>_<phase_name>
          field_id, phase_name = key[len(_CUSTOM_FIELD_NAME_PREFIX):].split(
              '_', 1)
          field_id = int(field_id)
        if post_data.get('op_' + key) == 'remove':
          if phase_name:
            phase_field_val_strs_remove[field_id][phase_name] = val_strs
          else:
            field_val_strs_remove[field_id] = val_strs
        else:
          if phase_name:
            phase_field_val_strs[field_id][phase_name] = val_strs
          else:
            field_val_strs[field_id] = val_strs

  # TODO(jojwang): monorail:5154, no support for clearing phase field values.
  fields_clear = []
  op_prefix = 'op_' + _CUSTOM_FIELD_NAME_PREFIX
  for op_key in post_data.keys():
    if op_key.startswith(op_prefix):
      if post_data.get(op_key) == 'clear':
        field_id = int(op_key[len(op_prefix):])
        fields_clear.append(field_id)

  return ParsedFields(
      field_val_strs, field_val_strs_remove, fields_clear,
      phase_field_val_strs, phase_field_val_strs_remove)


def _ParseIssueRequestAttachments(post_data):
  """Extract and clean-up any attached files from the post data.

  Args:
    post_data: dict w/ values from the user's HTTP POST form data.

  Returns:
    [(filename, filecontents, mimetype), ...] with items for each attachment.
  """
  # TODO(jrobbins): change from numbered fields to a multi-valued field.
  attachments = []
  for i in range(1, 16):
    if 'file%s' % i in post_data:
      item = post_data['file%s' % i]
      if isinstance(item, string_types):
        continue
      if '\\' in item.filename:  # IE insists on giving us the whole path.
        item.filename = item.filename[item.filename.rindex('\\') + 1:]
      if not item.filename:
        continue  # Skip any FILE fields that were not filled in.
      attachments.append(
          (
              item.filename, item.read(),
              filecontent.GuessContentTypeFromFilename(item.filename)))

  return attachments


def _ParseIssueRequestKeptAttachments(post_data):
  """Extract attachment ids for attachments kept when updating description

  Args:
    post_data: dict w/ values from the user's HTTP POST form data.

  Returns:
    a list of attachment ids for kept attachments
  """
  kept_attachments = post_data.getlist('keep-attachment')
  return [int(aid) for aid in kept_attachments]


def _ParseIssueRequestUsers(cnxn, post_data, services):
  """Extract usernames from the POST data, categorize them, and look up IDs.

  Args:
    cnxn: connection to SQL database.
    post_data: dict w/ data from the HTTP POST.
    services: Services.

  Returns:
    A namedtuple (owner_username, owner_id, cc_usernames, cc_usernames_remove,
    cc_ids, cc_ids_remove), containing:
      - issue owner's name and user ID, if any
      - the list of all cc'd usernames
      - the user IDs to add or remove from the issue CC list.
    Any of these user IDs may be  None if the corresponding username
    or email address is invalid.
  """
  # Get the user-entered values from post_data.
  cc_username_str = post_data.get('cc', '').lower()
  owner_email = post_data.get('owner', '').strip().lower()

  cc_usernames, cc_usernames_remove = _ClassifyPlusMinusItems(
      re.split(r'[,;\s]+', cc_username_str))

  # Figure out the email addresses to lookup and do the lookup.
  emails_to_lookup = cc_usernames + cc_usernames_remove
  if owner_email:
    emails_to_lookup.append(owner_email)
  all_user_ids = services.user.LookupUserIDs(
      cnxn, emails_to_lookup, autocreate=True)
  if owner_email:
    owner_id = all_user_ids.get(owner_email)
  else:
    owner_id = framework_constants.NO_USER_SPECIFIED

  # Lookup the user IDs of the Cc addresses to add or remove.
  cc_ids = [all_user_ids.get(cc) for cc in cc_usernames if cc]
  cc_ids_remove = [all_user_ids.get(cc) for cc in cc_usernames_remove if cc]

  return ParsedUsers(owner_email, owner_id, cc_usernames, cc_usernames_remove,
                     cc_ids, cc_ids_remove)


def _ParseBlockers(cnxn, post_data, services, errors, default_project_name,
                   field_name):
  """Parse input for issues that the current issue is blocking/blocked on.

  Args:
    cnxn: connection to SQL database.
    post_data: dict w/ values from the user's HTTP POST.
    services: connections to backend services.
    errors: object to accumulate validation error info.
    default_project_name: name of the project that contains the issue.
    field_name: string HTML input field name, e.g., BLOCKED_ON or BLOCKING.

  Returns:
    A namedtuple with the user input string, and a list of issue IDs.
  """
  entered_str = post_data.get(field_name, '').strip()
  blocker_iids = []
  dangling_ref_tuples = []
  federated_ref_strings = []

  issue_ref = None
  for ref_str in re.split(r'[,;\s]+', entered_str):
    # Handle federated references.
    if federated.IsShortlinkValid(ref_str):
      federated_ref_strings.append(ref_str)
      continue

    try:
      issue_ref = tracker_bizobj.ParseIssueRef(ref_str)
    except ValueError:
      setattr(errors, field_name, 'Invalid issue ID %s' % ref_str.strip())
      break

    if not issue_ref:
      continue

    blocker_project_name, blocker_issue_id = issue_ref
    if not blocker_project_name:
      blocker_project_name = default_project_name

    # Detect and report if the same issue was specified.
    current_issue_id = int(post_data.get('id')) if post_data.get('id') else -1
    if (blocker_issue_id == current_issue_id and
        blocker_project_name == default_project_name):
      setattr(errors, field_name, 'Cannot be %s the same issue' % field_name)
      break

    ref_projects = services.project.GetProjectsByName(
        cnxn, set([blocker_project_name]))
    blocker_iid, _misses = services.issue.ResolveIssueRefs(
        cnxn, ref_projects, default_project_name, [issue_ref])
    if not blocker_iid:
      if blocker_project_name in settings.recognized_codesite_projects:
        # We didn't find the issue, but it had a explicitly-specified project
        # which we know is on Codesite. Allow it as a dangling reference.
        dangling_ref_tuples.append(issue_ref)
        continue
      else:
        # Otherwise, it doesn't exist, so report it.
        setattr(errors, field_name, 'Invalid issue ID %s' % ref_str.strip())
        break
    if blocker_iid[0] not in blocker_iids:
      blocker_iids.extend(blocker_iid)

  blocker_iids.sort()
  dangling_ref_tuples.sort()
  return ParsedBlockers(entered_str, blocker_iids, dangling_ref_tuples,
      federated_ref_strings)


def PairDerivedValuesWithRuleExplanations(
    proposed_issue, traces, derived_users_by_id):
  """Pair up values and explanations into JSON objects."""
  derived_labels_and_why = [
      {'value': lab,
       'why': traces.get((tracker_pb2.FieldID.LABELS, lab))}
      for lab in proposed_issue.derived_labels]

  derived_users_by_id = {
      user_id: user_view.display_name
      for user_id, user_view in derived_users_by_id.items()
      if user_view.display_name}

  derived_owner_and_why = []
  if proposed_issue.derived_owner_id:
    derived_owner_and_why = [{
        'value': derived_users_by_id[proposed_issue.derived_owner_id],
        'why': traces.get(
            (tracker_pb2.FieldID.OWNER, proposed_issue.derived_owner_id))}]
  derived_cc_and_why = [
      {'value': derived_users_by_id[cc_id],
       'why': traces.get((tracker_pb2.FieldID.CC, cc_id))}
      for cc_id in proposed_issue.derived_cc_ids
      if cc_id in derived_users_by_id]

  warnings_and_why = [
      {'value': warning,
       'why': traces.get((tracker_pb2.FieldID.WARNING, warning))}
      for warning in proposed_issue.derived_warnings]

  errors_and_why = [
      {'value': error,
       'why': traces.get((tracker_pb2.FieldID.ERROR, error))}
      for error in proposed_issue.derived_errors]

  return (derived_labels_and_why, derived_owner_and_why, derived_cc_and_why,
          warnings_and_why, errors_and_why)


def IsValidIssueOwner(cnxn, project, owner_id, services):
  """Return True if the given user ID can be an issue owner.

  Args:
    cnxn: connection to SQL database.
    project: the current Project PB.
    owner_id: the user ID of the proposed issue owner.
    services: connections to backends.

  It is OK to have 0 for the owner_id, that simply means that the issue is
  unassigned.

  Returns:
    A pair (valid, err_msg).  valid is True if the given user ID can be an
    issue owner. err_msg is an error message string to display to the user
    if valid == False, and is None if valid == True.
  """
  # An issue is always allowed to have no owner specified.
  if owner_id == framework_constants.NO_USER_SPECIFIED:
    return True, None

  try:
    auth = authdata.AuthData.FromUserID(cnxn, owner_id, services)
    if not framework_bizobj.UserIsInProject(project, auth.effective_ids):
      return False, 'Issue owner must be a project member.'
  except exceptions.NoSuchUserException:
    return False, 'Issue owner user ID not found.'

  group_ids = services.usergroup.DetermineWhichUserIDsAreGroups(
      cnxn, [owner_id])
  if owner_id in group_ids:
    return False, 'Issue owner cannot be a user group.'

  return True, None


def GetAllowedOpenedAndClosedIssues(mr, issue_ids, services):
  """Get filtered lists of open and closed issues identified by issue_ids.

  The function then filters the results to only the issues that the user
  is allowed to view.  E.g., we only auto-link to issues that the user
  would be able to view if they clicked the link.

  Args:
    mr: commonly used info parsed from the request.
    issue_ids: list of int issue IDs for the target issues.
    services: connection to issue, config, and project persistence layers.

  Returns:
    Two lists of issues that the user is allowed to view: one for open
    issues and one for closed issues.
  """
  open_issues, closed_issues = services.issue.GetOpenAndClosedIssues(
      mr.cnxn, issue_ids)
  return GetAllowedIssues(mr, [open_issues, closed_issues], services)


def GetAllowedIssues(mr, issue_groups, services):
  """Filter lists of issues identified by issue_groups.

  Args:
    mr: commonly used info parsed from the request.
    issue_groups: list of list of issues to filter.
    services: connection to issue, config, and project persistence layers.

  Returns:
    List of filtered list of issues.
  """

  project_dict = GetAllIssueProjects(
      mr.cnxn, itertools.chain.from_iterable(issue_groups), services.project)
  config_dict = services.config.GetProjectConfigs(mr.cnxn,
      list(project_dict.keys()))
  return [FilterOutNonViewableIssues(
      mr.auth.effective_ids, mr.auth.user_pb, project_dict, config_dict,
      issues)
          for issues in issue_groups]


def MakeViewsForUsersInIssues(cnxn, issue_list, user_service, omit_ids=None):
  """Lookup all the users involved in any of the given issues.

  Args:
    cnxn: connection to SQL database.
    issue_list: list of Issue PBs from a result query.
    user_service: Connection to User backend storage.
    omit_ids: a list of user_ids to omit, e.g., because we already have them.

  Returns:
    A dictionary {user_id: user_view,...} for all the users involved
    in the given issues.
  """
  issue_participant_id_set = tracker_bizobj.UsersInvolvedInIssues(issue_list)
  if omit_ids:
    issue_participant_id_set.difference_update(omit_ids)

  # TODO(jrobbins): consider caching View objects as well.
  users_by_id = framework_views.MakeAllUserViews(
      cnxn, user_service, issue_participant_id_set)

  return users_by_id


def FormatIssueListURL(
    mr, config, absolute=True, project_names=None, **kwargs):
  """Format a link back to list view as configured by user."""
  if project_names is None:
    project_names = [mr.project_name]
  if tracker_constants.JUMP_RE.match(mr.query):
    kwargs['q'] = 'id=%s' % mr.query
    kwargs['can'] = 1  # The specified issue might be closed.
  else:
    kwargs['q'] = mr.query
    if mr.can and mr.can != 2:
      kwargs['can'] = mr.can
  def_col_spec = config.default_col_spec
  if mr.col_spec and mr.col_spec != def_col_spec:
    kwargs['colspec'] = mr.col_spec
  if mr.sort_spec:
    kwargs['sort'] = mr.sort_spec
  if mr.group_by_spec:
    kwargs['groupby'] = mr.group_by_spec
  if mr.start:
    kwargs['start'] = mr.start
  if mr.num != tracker_constants.DEFAULT_RESULTS_PER_PAGE:
    kwargs['num'] = mr.num

  if len(project_names) == 1:
    url = '/p/%s%s' % (project_names[0], urls.ISSUE_LIST)
  else:
    url = urls.ISSUE_LIST
    kwargs['projects'] = ','.join(sorted(project_names))

  param_strings = [
      '%s=%s' % (k, urllib.parse.quote((u'%s' % v).encode('utf-8')))
      for k, v in kwargs.items()
  ]
  if param_strings:
    url += '?' + '&'.join(sorted(param_strings))
  if absolute:
    url = '%s://%s%s' % (mr.request.scheme, mr.request.host, url)

  return url


def FormatRelativeIssueURL(project_name, path, **kwargs):
  """Format a URL to get to an issue in the named project.

  Args:
    project_name: string name of the project containing the issue.
    path: string servlet path, e.g., from framework/urls.py.
    **kwargs: additional query-string parameters to include in the URL.

  Returns:
    A URL string.
  """
  return framework_helpers.FormatURL(
      None, '/p/%s%s' % (project_name, path), **kwargs)


def FormatCrBugURL(project_name, local_id):
  """Format a short URL to get to an issue in the named project.

  Args:
    project_name: string name of the project containing the issue.
    local_id: int local ID of the issue.

  Returns:
    A URL string.
  """
  if app_identity.get_application_id() != 'monorail-prod':
    return FormatRelativeIssueURL(
      project_name, urls.ISSUE_DETAIL, id=local_id)

  if project_name == 'chromium':
    return 'https://crbug.com/%d' % local_id

  return 'https://crbug.com/%s/%d' % (project_name, local_id)


def ComputeNewQuotaBytesUsed(project, attachments):
  """Add the given attachments to the project's attachment quota usage.

  Args:
    project: Project PB  for the project being updated.
    attachments: a list of attachments being added to an issue.

  Returns:
    The new number of bytes used.

  Raises:
    OverAttachmentQuota: If project would go over quota.
  """
  total_attach_size = 0
  for _filename, content, _mimetype in attachments:
    total_attach_size += len(content)

  new_bytes_used = project.attachment_bytes_used + total_attach_size
  quota = (project.attachment_quota or
           tracker_constants.ISSUE_ATTACHMENTS_QUOTA_HARD)
  if new_bytes_used > quota:
    raise exceptions.OverAttachmentQuota(new_bytes_used - quota)
  return new_bytes_used


def IsUnderSoftAttachmentQuota(project):
  """Check the project's attachment quota against the soft quota limit.

  If there is a custom quota on the project, this will check against
  that instead of the system-wide default quota.

  Args:
    project: Project PB for the project to examine

  Returns:
    True if the project is under quota, false otherwise.
  """
  quota = tracker_constants.ISSUE_ATTACHMENTS_QUOTA_SOFT
  if project.attachment_quota:
    quota = project.attachment_quota - _SOFT_QUOTA_LEEWAY

  return project.attachment_bytes_used < quota


def GetAllIssueProjects(cnxn, issues, project_service):
  """Get all the projects that the given issues belong to.

  Args:
    cnxn: connection to SQL database.
    issues: list of issues, which may come from different projects.
    project_service: connection to project persistence layer.

  Returns:
    A dictionary {project_id: project} of all the projects that
    any of the given issues belongs to.
  """
  needed_project_ids = {issue.project_id for issue in issues}
  project_dict = project_service.GetProjects(cnxn, needed_project_ids)
  return project_dict


def GetPermissionsInAllProjects(user, effective_ids, projects):
  """Look up the permissions for the given user in each project."""
  return {
      project.project_id:
      permissions.GetPermissions(user, effective_ids, project)
      for project in projects}


def FilterOutNonViewableIssues(
    effective_ids, user, project_dict, config_dict, issues):
  """Return a filtered list of issues that the user can view."""
  perms_dict = GetPermissionsInAllProjects(
      user, effective_ids, list(project_dict.values()))

  denied_project_ids = {
      pid for pid, p in project_dict.items()
      if not permissions.CanView(effective_ids, perms_dict[pid], p, [])}

  results = []
  for issue in issues:
    if issue.deleted or issue.project_id in denied_project_ids:
      continue

    if not permissions.HasRestrictions(issue):
      may_view = True
    else:
      perms = perms_dict[issue.project_id]
      project = project_dict[issue.project_id]
      config = config_dict.get(issue.project_id, config_dict.get('harmonized'))
      granted_perms = tracker_bizobj.GetGrantedPerms(
          issue, effective_ids, config)
      may_view = permissions.CanViewIssue(
          effective_ids, perms, project, issue, granted_perms=granted_perms)

    if may_view:
      results.append(issue)

  return results


def MeansOpenInProject(status, config):
  """Return true if this status means that the issue is still open.

  This defaults to true if we could not find a matching status.

  Args:
    status: issue status string. E.g., 'New'.
    config: the config of the current project.

  Returns:
    Boolean True if the status means that the issue is open.
  """
  status_lower = status.lower()

  # iterate over the list of known statuses for this project
  # return true if we find a match that declares itself to be open
  for wks in config.well_known_statuses:
    if wks.status.lower() == status_lower:
      return wks.means_open

  return True


def IsNoisy(num_comments, num_starrers):
  """Return True if this is a "noisy" issue that would send a ton of emails.

  The rule is that a very active issue with a large number of comments
  and starrers will only send notification when a comment (or change)
  is made by a project member.

  Args:
    num_comments: int number of comments on issue so far.
    num_starrers: int number of users who starred the issue.

  Returns:
    True if we will not bother starrers with an email notification for
    changes made by non-members.
  """
  return (num_comments >= tracker_constants.NOISY_ISSUE_COMMENT_COUNT and
          num_starrers >= tracker_constants.NOISY_ISSUE_STARRER_COUNT)


def MergeCCsAndAddComment(services, mr, issue, merge_into_issue):
  """Modify the CC field of the target issue and add a comment to it."""
  return MergeCCsAndAddCommentMultipleIssues(
      services, mr, [issue], merge_into_issue)


def MergeCCsAndAddCommentMultipleIssues(
    services, mr, issues, merge_into_issue):
  """Modify the CC field of the target issue and add a comment to it."""
  merge_comment = ''
  for issue in issues:
    if issue.project_name == merge_into_issue.project_name:
      issue_ref_str = '%d' % issue.local_id
    else:
      issue_ref_str = '%s:%d' % (issue.project_name, issue.local_id)
    if merge_comment:
      merge_comment += '\n'
    merge_comment += 'Issue %s has been merged into this issue.' % issue_ref_str

  add_cc = _ComputeNewCcsFromIssueMerge(merge_into_issue, issues)

  config = services.config.GetProjectConfig(
      mr.cnxn, merge_into_issue.project_id)
  delta = tracker_pb2.IssueDelta(cc_ids_add=add_cc)
  _, merge_comment_pb = services.issue.DeltaUpdateIssue(
    mr.cnxn, services, mr.auth.user_id, merge_into_issue.project_id,
    config, merge_into_issue, delta, index_now=False, comment=merge_comment)

  return merge_comment_pb


def GetAttachmentIfAllowed(mr, services):
  """Retrieve the requested attachment, or raise an appropriate exception.

  Args:
    mr: commonly used info parsed from the request.
    services: connections to backend services.

  Returns:
    The requested Attachment PB, and the Issue that it belongs to.

  Raises:
    NoSuchAttachmentException: attachment was not found or was marked deleted.
    NoSuchIssueException: issue that contains attachment was not found.
    PermissionException: the user is not allowed to view the attachment.
  """
  attachment = None

  attachment, cid, issue_id = services.issue.GetAttachmentAndContext(
      mr.cnxn, mr.aid)

  issue = services.issue.GetIssue(mr.cnxn, issue_id)
  config = services.config.GetProjectConfig(mr.cnxn, issue.project_id)
  granted_perms = tracker_bizobj.GetGrantedPerms(
      issue, mr.auth.effective_ids, config)
  permit_view = permissions.CanViewIssue(
      mr.auth.effective_ids, mr.perms, mr.project, issue,
      granted_perms=granted_perms)
  if not permit_view:
    raise permissions.PermissionException('Cannot view attachment\'s issue')

  comment = services.issue.GetComment(mr.cnxn, cid)
  commenter = services.user.GetUser(mr.cnxn, comment.user_id)
  issue_perms = permissions.UpdateIssuePermissions(
      mr.perms, mr.project, issue, mr.auth.effective_ids,
      granted_perms=granted_perms)
  can_view_comment = permissions.CanViewComment(
      comment, commenter, mr.auth.user_id, issue_perms)
  if not can_view_comment:
    raise permissions.PermissionException('Cannot view attachment\'s comment')

  return attachment, issue


def LabelsMaskedByFields(config, field_names, trim_prefix=False):
  """Return a list of EZTItems for labels that would be masked by fields."""
  return _LabelsMaskedOrNot(config, field_names, trim_prefix=trim_prefix)


def LabelsNotMaskedByFields(config, field_names, trim_prefix=False):
  """Return a list of EZTItems for labels that would not be masked."""
  return _LabelsMaskedOrNot(
      config, field_names, invert=True, trim_prefix=trim_prefix)


def _LabelsMaskedOrNot(config, field_names, invert=False, trim_prefix=False):
  """Return EZTItems for labels that'd be masked. Or not, when invert=True."""
  field_names = [fn.lower() for fn in field_names]
  result = []
  for wkl in config.well_known_labels:
    masked_by = tracker_bizobj.LabelIsMaskedByField(wkl.label, field_names)
    if (masked_by and not invert) or (not masked_by and invert):
      display_name = wkl.label
      if trim_prefix:
        display_name = display_name[len(masked_by) + 1:]
      result.append(template_helpers.EZTItem(
          name=display_name,
          name_padded=display_name.ljust(20),
          commented='#' if wkl.deprecated else '',
          docstring=wkl.label_docstring,
          docstring_short=template_helpers.FitUnsafeText(
              wkl.label_docstring, 40),
          idx=len(result)))

  return result


def LookupComponentIDs(component_paths, config, errors=None):
  """Look up the IDs of the specified components in the given config."""
  component_ids = []
  for path in component_paths:
    if not path:
      continue
    cd = tracker_bizobj.FindComponentDef(path, config)
    if cd:
      component_ids.append(cd.component_id)
    else:
      error_text = 'Unknown component %s' % path
      if errors:
        errors.components = error_text
      else:
        logging.info(error_text)

  return component_ids


def ParsePostDataUsers(cnxn, pd_users_str, user_service):
  """Parse all the usernames from a users string found in a post data."""
  emails, _remove = _ClassifyPlusMinusItems(re.split(r'[,;\s]+', pd_users_str))
  users_ids_by_email = user_service.LookupUserIDs(cnxn, emails, autocreate=True)
  user_ids = [users_ids_by_email[username] for username in emails if username]
  return user_ids, pd_users_str


def FilterIssueTypes(config):
  """Return a list of well-known issue types."""
  well_known_issue_types = []
  for wk_label in config.well_known_labels:
    if wk_label.label.lower().startswith('type-'):
      _, type_name = wk_label.label.split('-', 1)
      well_known_issue_types.append(type_name)

  return well_known_issue_types


def ParseMergeFields(
    cnxn, services, project_name, post_data, status, config, issue, errors):
  """Parse info that identifies the issue to merge into, if any."""
  merge_into_text = ''
  merge_into_ref = None
  merge_into_issue = None

  if status not in config.statuses_offer_merge:
    return '', None

  merge_into_text = post_data.get('merge_into', '')
  if merge_into_text:
    try:
      merge_into_ref = tracker_bizobj.ParseIssueRef(merge_into_text)
    except ValueError:
      logging.info('merge_into not an int: %r', merge_into_text)
      errors.merge_into_id = 'Please enter a valid issue ID'

  if not merge_into_ref:
    errors.merge_into_id = 'Please enter an issue ID'
    return merge_into_text, None

  merge_into_project_name, merge_into_id = merge_into_ref
  if (merge_into_id == issue.local_id and
      (merge_into_project_name == project_name or
       not merge_into_project_name)):
    logging.info('user tried to merge issue into itself: %r', merge_into_ref)
    errors.merge_into_id = 'Cannot merge issue into itself'
    return merge_into_text, None

  project = services.project.GetProjectByName(
      cnxn, merge_into_project_name or project_name)
  try:
    # Because we will modify this issue, load from DB rather than cache.
    merge_into_issue = services.issue.GetIssueByLocalID(
        cnxn, project.project_id, merge_into_id, use_cache=False)
  except Exception:
    logging.info('merge_into issue not found: %r', merge_into_ref)
    errors.merge_into_id = 'No such issue'
    return merge_into_text, None

  return merge_into_text, merge_into_issue


def GetNewIssueStarrers(cnxn, services, issue_ids, merge_into_iid):
  # type: (MonorailConnection, Services, Sequence[int], int) ->
  #     Collection[int]
  """Get starrers of current issue who have not starred the target issue."""
  source_starrers_dict = services.issue_star.LookupItemsStarrers(
      cnxn, issue_ids)
  source_starrers = list(
      itertools.chain.from_iterable(source_starrers_dict.values()))
  target_starrers = services.issue_star.LookupItemStarrers(
      cnxn, merge_into_iid)
  return set(source_starrers) - set(target_starrers)


def AddIssueStarrers(
    cnxn, services, mr, merge_into_iid, merge_into_project, new_starrers):
  """Merge all the starrers for the current issue into the target issue."""
  project = merge_into_project or mr.project
  config = services.config.GetProjectConfig(mr.cnxn, project.project_id)
  services.issue_star.SetStarsBatch(
      cnxn, services, config, merge_into_iid, new_starrers, True)


def CanEditProjectIssue(mr, project, issue, granted_perms):
  """Check if user permissions in another project allow editing.

  Wraps CanEditIssue with a call to get user permissions in given project.

  We deviate from using CanUsePerm because that method does not calculate
  Project state as part of the permissions. This seems to have deviated in
  2018. CanEditIssue uses Project state to authorize user actions.
  """
  project_perms = permissions.GetPermissions(
      mr.auth.user_pb, mr.auth.effective_ids, project)
  return permissions.CanEditIssue(
      mr.auth.effective_ids, project_perms, project, issue, granted_perms)


def GetVisibleMembers(mr, project, services):
  all_member_ids = project_helpers.AllProjectMembers(project)

  all_group_ids = services.usergroup.DetermineWhichUserIDsAreGroups(
      mr.cnxn, all_member_ids)

  (ac_exclusion_ids, no_expand_ids
   ) = services.project.GetProjectAutocompleteExclusion(
      mr.cnxn, project.project_id)

  group_ids_to_expand = [
    gid for gid in all_group_ids if gid not in no_expand_ids]

  # TODO(jrobbins): Normally, users will be allowed view the members
  # of any user group if the project From: email address is listed
  # as a group member, as well as any group that they are personally
  # members of.
  member_ids, owner_ids = services.usergroup.LookupVisibleMembers(
      mr.cnxn, group_ids_to_expand, mr.perms, mr.auth.effective_ids, services)
  indirect_user_ids = set()
  for gids in member_ids.values():
    indirect_user_ids.update(gids)
  for gids in owner_ids.values():
    indirect_user_ids.update(gids)

  visible_member_ids = _FilterMemberData(
      mr, project.owner_ids, project.committer_ids, project.contributor_ids,
      indirect_user_ids, project)

  visible_member_ids = _MergeLinkedMembers(
      mr.cnxn, services.user, visible_member_ids)

  visible_member_views = framework_views.MakeAllUserViews(
      mr.cnxn, services.user, visible_member_ids, group_ids=all_group_ids)
  framework_views.RevealAllEmailsToMembers(
      mr.cnxn, services, mr.auth, visible_member_views, project)

  # Filter out service accounts
  service_acct_emails = set(
      client_config_svc.GetClientConfigSvc().GetClientIDEmails()[1])
  visible_member_views = {
      m.user_id: m
      for m in visible_member_views.values()
      # Hide service accounts from autocomplete.
      if not framework_helpers.IsServiceAccount(
          m.email, client_emails=service_acct_emails)
      # Hide users who opted out of autocomplete.
      and not m.user_id in ac_exclusion_ids
      # Hide users who have obscured email addresses.
      and not m.obscure_email
  }

  return visible_member_views


def _MergeLinkedMembers(cnxn, user_service, user_ids):
  """Remove any linked child accounts if the parent would also be shown."""
  all_ids = set(user_ids)
  users_by_id = user_service.GetUsersByIDs(cnxn, user_ids)
  result = [uid for uid in user_ids
            if users_by_id[uid].linked_parent_id not in all_ids]
  return result


def _FilterMemberData(
    mr, owner_ids, committer_ids, contributor_ids, indirect_member_ids,
    project):
  """Return a filtered list of members that the user can view.

  In most projects, everyone can view the entire member list.  But,
  some projects are configured to only allow project owners to see
  all members. In those projects, committers and contributors do not
  see any contributors.  Regardless of how the project is configured
  or the role that the user plays in the current project, we include
  any indirect members through user groups that the user has access
  to view.

  Args:
    mr: Commonly used info parsed from the HTTP request.
    owner_views: list of user IDs for project owners.
    committer_views: list of user IDs for project committers.
    contributor_views: list of user IDs for project contributors.
    indirect_member_views: list of user IDs for users who have
        an indirect role in the project via a user group, and that the
        logged in user is allowed to see.
    project: the Project we're interested in.

  Returns:
    A list of owners, committer and visible indirect members if the user is not
    signed in.  If the project is set to display contributors to non-owners or
    the signed in user has necessary permissions then additionally a list of
    contributors.
  """
  visible_members_ids = set()

  # Everyone can view owners and committers
  visible_members_ids.update(owner_ids)
  visible_members_ids.update(committer_ids)

  # The list of indirect members is already limited to ones that the user
  # is allowed to see according to user group settings.
  visible_members_ids.update(indirect_member_ids)

  # If the user is allowed to view the list of contributors, add those too.
  if permissions.CanViewContributorList(mr, project):
    visible_members_ids.update(contributor_ids)

  return sorted(visible_members_ids)


def GetLabelOptions(config, custom_permissions):
  """Prepares label options for autocomplete."""
  labels = []
  field_names = [
    fd.field_name
    for fd in config.field_defs
    if not fd.is_deleted
    and fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
  ]
  non_masked_labels = LabelsNotMaskedByFields(config, field_names)
  for wkl in non_masked_labels:
    if not wkl.commented:
      item = {'name': wkl.name, 'doc': wkl.docstring}
      labels.append(item)

  frequent_restrictions = _FREQUENT_ISSUE_RESTRICTIONS[:]
  if not custom_permissions:
    frequent_restrictions.extend(_EXAMPLE_ISSUE_RESTRICTIONS)

  labels.extend(_BuildRestrictionChoices(
      frequent_restrictions, permissions.STANDARD_ISSUE_PERMISSIONS,
      custom_permissions))

  return labels


def _BuildRestrictionChoices(freq_restrictions, actions, custom_permissions):
  """Return a list of autocompletion choices for restriction labels.

  Args:
    freq_restrictions: list of (action, perm, doc) tuples for restrictions
        that are frequently used.
    actions: list of strings for actions that are relevant to the current
      artifact.
    custom_permissions: list of strings with custom permissions for the project.

  Returns:
    A list of dictionaries [{'name': 'perm name', 'doc': 'docstring'}, ...]
    suitable for use in a JSON feed to our JS autocompletion functions.
  """
  choices = []

  for action, perm, doc in freq_restrictions:
    choices.append({
        'name': 'Restrict-%s-%s' % (action, perm),
        'doc': doc,
        })

  for action in actions:
    for perm in custom_permissions:
      choices.append({
          'name': 'Restrict-%s-%s' % (action, perm),
          'doc': 'Permission %s needed to use %s' % (perm, action),
          })

  return choices


def FilterKeptAttachments(
    is_description, kept_attachments, comments, approval_id):
  """Filter kept attachments to be a subset of last description's attachments.

  Args:
    is_description: bool, if the comment is a change to the issue description.
    kept_attachments: list of ints with the attachment ids for attachments
        kept from previous descriptions, if the comment is a change to the
        issue description.
    comments: list of IssueComment PBs for the issue we want to edit.
    approval_id: int id of the APPROVAL_TYPE fielddef, if we're editing an
        approval description, or None otherwise.

  Returns:
    A list of kept_attachment ids that are a subset of the last description.
  """
  if not is_description:
    return None

  attachment_ids = set()
  for comment in reversed(comments):
    if comment.is_description and comment.approval_id == approval_id:
      attachment_ids = set([a.attachment_id for a in comment.attachments])
      break

  kept_attachments = [
      aid for aid in kept_attachments if aid in attachment_ids]
  return kept_attachments


def _GetEnumFieldValuesAndDocstrings(field_def, config):
  # type: (mrproto.tracker_pb2.LabelDef,
  #   mrproto.tracker_pb2.ProjectIssueConfig) -> Sequence[tuple(string, string)]
  """Get sequence of value, docstring tuples for an enum field"""
  label_defs = config.well_known_labels
  lower_field_name = field_def.field_name.lower()
  tuples = []
  for ld in label_defs:
    if (ld.label.lower().startswith(lower_field_name + '-') and
        not ld.deprecated):
      label_value = ld.label[len(lower_field_name) + 1:]
      tuples.append((label_value, ld.label_docstring))
    else:
      continue
  return tuples


# _IssueChangesTuple is returned by ApplyAllIssueChanges() and is used to bundle
# the updated issues. resulting amendments, and other information needed by the
# called to process the changes in the DB and send notifications.
_IssueChangesTuple = collections.namedtuple(
    '_IssueChangesTuple', [
        'issues_to_update_dict', 'merged_from_add_by_iid', 'amendments_by_iid',
        'imp_amendments_by_iid', 'old_owners_by_iid', 'old_statuses_by_iid',
        'old_components_by_iid', 'new_starrers_by_iid'
    ])
# type: (Mapping[int, Issue], DefaultDict[int, Sequence[int]],
#     Mapping[int, Amendment], Mapping[int, Amendment], Mapping[int, int],
#     Mapping[int, str], Mapping[int, Sequence[int]],
#     Mapping[int, Sequence[int]])-> None


def ApplyAllIssueChanges(cnxn, issue_delta_pairs, services):
  # type: (MonorailConnection, Sequence[Tuple[Issue, IssueDelta]], Services) ->
  #     IssueChangesTuple
  """Modify the given issues with the given deltas and impacted issues in RAM.

    Filter rules are not applied in this method.
    This method implements phases 3 and 4 of the process for modifying issues.
    See WorkEnv.ModifyIssues() for other phases and overall process.

    Args:
      cnxn: MonorailConnection object.
      issue_delta_pairs: List of tuples that couple Issues with the IssueDeltas
          that represent the updates we want to make to each Issue.
      services: Services object for connection to backend services.

    Returns:
      An _IssueChangesTuple named tuple.
  """
  impacted_tracker = _IssueChangeImpactedIssues()
  project_ids = {issue.project_id for issue, _delta in issue_delta_pairs}
  configs_by_pid = services.config.GetProjectConfigs(cnxn, list(project_ids))

  # Track issues which have been modified in RAM and will need to
  # be updated in the DB.
  issues_to_update_dict = {}

  amendments_by_iid = {}
  old_owners_by_iid = {}
  old_statuses_by_iid = {}
  old_components_by_iid = {}
  # PHASE 3: Update the main issues in RAM (not indirectly, impacted issues).
  for issue, delta in issue_delta_pairs:
    # Cache old data that will be used by future computations.
    old_owner = tracker_bizobj.GetOwnerId(issue)
    old_status = tracker_bizobj.GetStatus(issue)
    if delta.owner_id is not None and delta.owner_id != old_owner:
      old_owners_by_iid[issue.issue_id] = old_owner
    if delta.status is not None and delta.status != old_status:
      old_statuses_by_iid[issue.issue_id] = old_status
    new_components = set(issue.component_ids)
    new_components.update(delta.comp_ids_add or [])
    new_components.difference_update(delta.comp_ids_remove or [])
    if set(issue.component_ids) != new_components:
      old_components_by_iid[issue.issue_id] = issue.component_ids

    impacted_tracker.TrackImpactedIssues(issue, delta)
    config = configs_by_pid.get(issue.project_id)
    amendments, _impacted_iids = tracker_bizobj.ApplyIssueDelta(
        cnxn, services.issue, issue, delta, config)
    if amendments:
      issues_to_update_dict[issue.issue_id] = issue
      amendments_by_iid[issue.issue_id] = amendments

  # PHASE 4: Update impacted issues in RAM.
  logging.info('Applying impacted issue changes: %r', impacted_tracker.__dict__)
  imp_amendments_by_iid = {}
  impacted_iids = impacted_tracker.ComputeAllImpactedIIDs()
  new_starrers_by_iid = {}
  for issue_id in impacted_iids:
    # Changes made to an impacted issue should be on top of changes
    # made to it in PHASE 3 where it might have been a 'main' issue.
    issue = issues_to_update_dict.get(
        issue_id, services.issue.GetIssue(cnxn, issue_id, use_cache=False))

    # Apply impacted changes.
    amendments, new_starrers = impacted_tracker.ApplyImpactedIssueChanges(
        cnxn, issue, services)
    if amendments:
      imp_amendments_by_iid[issue.issue_id] = amendments
      issues_to_update_dict[issue.issue_id] = issue
      if new_starrers:
        new_starrers_by_iid[issue.issue_id] = new_starrers

  return _IssueChangesTuple(
      issues_to_update_dict, impacted_tracker.merged_from_add,
      amendments_by_iid, imp_amendments_by_iid, old_owners_by_iid,
      old_statuses_by_iid, old_components_by_iid, new_starrers_by_iid)


def UpdateClosedTimestamp(config, issue, old_effective_status):
  # type: (mrproto.tracker_pb2.ProjectIssueConfig,
  #   mrproto.tracker_pb2.Issue, str) -> None
  """Sets or unsets the closed_timestamp based based on status changes.

  If the status is changing from open to closed, the closed_timestamp is set to
  the current time.

  If the status is changing form closed to open, the close_timestamp is unset.

  If the status is changing from one closed to another closed, or from one
  open to another open, no operations are performed.

  Args:
    config: the project configuration
    issue: the issue being updated (a protocol buffer)
    old_effective_status: the old issue status string. E.g., 'New'

  SIDE EFFECTS:
    Updated issue in place with new closed timestamp.
  """
  old_effective_status = old_effective_status or ''
  # open -> closed
  if (MeansOpenInProject(old_effective_status, config) and
      not MeansOpenInProject(tracker_bizobj.GetStatus(issue), config)):

    issue.closed_timestamp = int(time.time())
    return

  # closed -> open
  if (not MeansOpenInProject(old_effective_status, config) and
      MeansOpenInProject(tracker_bizobj.GetStatus(issue), config)):

    issue.reset('closed_timestamp')
    return


def GroupUniqueDeltaIssues(issue_delta_pairs):
  # type: (Tuple[Issue, IssueDelta]) -> (
  #     Sequence[IssueDelta], Sequence[Sequence[Issue]])
  """Identifies unique IssueDeltas and groups Issues with identical IssueDeltas.

    Args:
      issue_delta_pairs: List of tuples that couple Issues with the IssueDeltas
          that represent the updates we want to make to each Issue.

    Returns:
      (unique_deltas, issues_for_unique_deltas):
      unique_deltas: List of unique IssueDeltas found in issue_delta_pairs.
      issues_for_unique_deltas: List of Issue lists. Each Issue list
              contains all the Issues that had identical IssueDeltas.
              Each issues_for_unique_deltas[i] is the list of Issues
              that had unique_deltas[i] as their IssueDeltas.
  """
  unique_deltas = []
  issues_for_unique_deltas = []
  for issue, delta in issue_delta_pairs:
    try:
      delta_index = unique_deltas.index(delta)
      issues_for_unique_deltas[delta_index].append(issue)
    except ValueError:
      # delta is not in unique_deltas yet.
      # Add delta to unique_deltas and add a new list of issues
      # to issues_for_unique_deltas at the same index.
      unique_deltas.append(delta)
      issues_for_unique_deltas.append([issue])

  return unique_deltas, issues_for_unique_deltas


def _AssertNoConflictingDeltas(issue_delta_pairs, refs_dict, err_agg):
  # type: (Sequence[Tuple[Issue, IssueDelta]], Mapping[int, str],
  #     exceptions.ErrorAggregator) -> None
  """Checks if any issue deltas conflict with each other or themselves.

  Note: refs_dict should contain issue ref strings for all issues found
      in issue_delta_pairs, including all issues found in
      {blocked_on|blocking}_{add|remove}.
  """
  err_message = 'Changes for {} conflict for {}'

  # Track all delta blocked_on_add and blocking_add in terms of
  # 'blocking_add' so we can track when a {blocked_on|blocking}_remove
  # is in conflict with some {blocked_on|blocking}_add.
  blocking_add = collections.defaultdict(list)
  for issue, delta in issue_delta_pairs:
    blocking_add[issue.issue_id].extend(delta.blocking_add)

    for imp_iid in delta.blocked_on_add:
      blocking_add[imp_iid].append(issue.issue_id)

  # Check *_remove for conflicts with tracking blocking_add.
  for issue, delta in issue_delta_pairs:
    added_iids = blocking_add[issue.issue_id]
    # Get intersection of iids that are in `blocking_remove` and
    # the tracked `blocking_add`.
    conflict_iids = set(delta.blocking_remove) & set(added_iids)

    # Get iids of `blocked_on_remove` that conflict with the
    # tracked `blocking_add`.
    for possible_conflict_iid in delta.blocked_on_remove:
      if issue.issue_id in blocking_add[possible_conflict_iid]:
        conflict_iids.add(possible_conflict_iid)

    if conflict_iids:
      refs_str = ', '.join([refs_dict[iid] for iid in conflict_iids])
      err_agg.AddErrorMessage(err_message, refs_dict[issue.issue_id], refs_str)


def PrepareIssueChanges(
    cnxn,
    issue_delta_pairs,
    services,
    attachment_uploads=None,
    comment_content=None):
  # type: (MonorailConnection, Sequence[Tuple[Issue, IssueDelta]], Services,
  #     Optional[Sequence[framework_helpers.AttachmentUpload]], Optional[str])
  #     -> Mapping[int, int]
  """Clean the deltas and assert they are valid for each paired issue."""
  _EnforceNonMergeStatusDeltas(cnxn, issue_delta_pairs, services)
  _AssertIssueChangesValid(
      cnxn, issue_delta_pairs, services, comment_content=comment_content)

  if attachment_uploads:
    return _EnforceAttachmentQuotaLimits(
        cnxn, issue_delta_pairs, services, attachment_uploads)
  return {}


def _EnforceAttachmentQuotaLimits(
    cnxn, issue_delta_pairs, services, attachment_uploads):
  # type: (MonorailConnection, Sequence[Tuple[Issue, IssueDelta]], Services
  #     Optional[Sequence[framework_helpers.AttachmentUpload]]
  #     -> Mapping[int, int]
  """Assert that the attachments don't exceed project quotas."""
  issue_count_by_pid = collections.defaultdict(int)
  for issue, _delta in issue_delta_pairs:
    issue_count_by_pid[issue.project_id] += 1

  projects_by_id = services.project.GetProjects(cnxn, issue_count_by_pid.keys())

  new_bytes_by_pid = {}
  with exceptions.ErrorAggregator(exceptions.OverAttachmentQuota) as err_agg:
    for pid, count in sorted(issue_count_by_pid.items()):
      project = projects_by_id[pid]
      try:
        new_bytes_used = ComputeNewQuotaBytesUsed(
            project, attachment_uploads * count)
        new_bytes_by_pid[pid] = new_bytes_used
      except exceptions.OverAttachmentQuota:
        err_agg.AddErrorMessage(
            'Attachment quota exceeded for project {}', project.project_name)
  return new_bytes_by_pid


def _AssertIssueChangesValid(
    cnxn, issue_delta_pairs, services, comment_content=None):
  # type: (MonorailConnection, Sequence[Tuple[Issue, IssueDelta]], Services,
  #     Optional[str]) -> None
  """Assert that the delta changes are valid for each paired issue.

    Note: this method does not check if the changes trigger any FilterRule
      `warnings` or `errors`.
  """
  project_ids = list(
      {issue.project_id for (issue, _delta) in issue_delta_pairs})
  projects_by_id = services.project.GetProjects(cnxn, project_ids)
  configs_by_id = services.config.GetProjectConfigs(cnxn, project_ids)
  refs_dict = {
      iss.issue_id: '%s:%d' % (iss.project_name, iss.local_id)
      for iss, _delta in issue_delta_pairs
  }
  # Add refs of deltas' blocking/blocked_on issues needed by
  # _AssertNoConflictingDeltas.
  relation_iids = set()
  for _iss, delta in issue_delta_pairs:
    relation_iids.update(
        delta.blocked_on_remove + delta.blocking_remove + delta.blocked_on_add +
        delta.blocking_add)
  relation_issues_dict, misses = services.issue.GetIssuesDict(
      cnxn, relation_iids)
  if misses:
    raise exceptions.NoSuchIssueException(
        'Could not find issues with ids: %r' % misses)
  for iid, iss in relation_issues_dict.items():
    if iid not in refs_dict:
      refs_dict[iid] = '%s:%d' % (iss.project_name, iss.local_id)

  with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
    if (comment_content and
        len(comment_content.strip()) > tracker_constants.MAX_COMMENT_CHARS):
      err_agg.AddErrorMessage('Comment is too long.')

    _AssertNoConflictingDeltas(issue_delta_pairs, refs_dict, err_agg)

    for issue, delta in issue_delta_pairs:
      project = projects_by_id.get(issue.project_id)
      config = configs_by_id.get(issue.project_id)
      issue_ref = refs_dict[issue.issue_id]

      if (delta.merged_into is not None or
          delta.merged_into_external is not None or delta.status is not None):
        end_status = delta.status or issue.status
        merged_options = [
            delta.merged_into, delta.merged_into_external, issue.merged_into,
            issue.merged_into_external
        ]
        end_merged_into = next(
            (merge for merge in merged_options if merge is not None), None)

        is_merge_status = end_status.lower() in [
            status.lower() for status in config.statuses_offer_merge
        ]

        if ((is_merge_status and not end_merged_into) or
            (not is_merge_status and end_merged_into)):
          err_agg.AddErrorMessage(
              '{}: MERGED type statuses must accompany mergedInto values.',
              issue_ref)

      if delta.merged_into and issue.issue_id == delta.merged_into:
        err_agg.AddErrorMessage(
            '{}: Cannot merge an issue into itself.', issue_ref)
      if (issue.issue_id in set(
          delta.blocked_on_add)) or (issue.issue_id in set(delta.blocking_add)):
        err_agg.AddErrorMessage(
            '{}: Cannot block an issue on itself.', issue_ref)
      if (delta.owner_id is not None) and (delta.owner_id != issue.owner_id):
        parsed_owner_valid, msg = IsValidIssueOwner(
            cnxn, project, delta.owner_id, services)
        if not parsed_owner_valid:
          err_agg.AddErrorMessage('{}: {}', issue_ref, msg)
      # Owner already check by IsValidIssueOwner
      all_users = [uid for uid in delta.cc_ids_add]
      field_users = [fv.user_id for fv in delta.field_vals_add if fv.user_id]
      all_users.extend(field_users)
      AssertUsersExist(cnxn, services, all_users, err_agg)
      if (delta.summary and
          len(delta.summary.strip()) > tracker_constants.MAX_SUMMARY_CHARS):
        err_agg.AddErrorMessage('{}: Summary is too long.', issue_ref)
      if delta.summary == '':
        err_agg.AddErrorMessage('{}: Summary required.', issue_ref)
      if delta.status == '':
        err_agg.AddErrorMessage('{}: Status is required.', issue_ref)
      labels_err_msgs = field_helpers.ValidateLabels(
          cnxn, services, issue.project_id, delta.labels_add)
      if labels_err_msgs:
        err_agg.AddErrorMessage('{}: {}', issue_ref, labels_err_msgs)
      # Do not pass in issue for validation, as issue is pre-update, and would
      # result in being unable to edit issues in invalid states.
      fvs_err_msgs = field_helpers.ValidateCustomFields(
          cnxn, services, delta.field_vals_add, config, project)
      if fvs_err_msgs:
        err_agg.AddErrorMessage('{}: {}', issue_ref, '\n'.join(fvs_err_msgs))
      # TODO(crbug.com/monorail/9156): Validate that we do not remove fields
      # such that a required field becomes unset.


def AssertUsersExist(cnxn, services, user_ids, err_agg):
  # type: (MonorailConnection, Services, Sequence[int], ErrorAggregator) -> None
  """Assert that all users exist.

    Has the side-effect of adding error messages to the input ErrorAggregator.
  """
  users_dict = services.user.GetUsersByIDs(cnxn, user_ids, skip_missed=True)
  found_ids = set(users_dict.keys())
  missing = [user_id for user_id in user_ids if user_id not in found_ids]
  for missing_user_id in missing:
    err_agg.AddErrorMessage(
        'users/{}: User does not exist.'.format(missing_user_id))


def AssertValidIssueForCreate(cnxn, services, issue, description):
  # type: (MonorailConnection, Services, Issue, str) -> None
  """Assert that issue proto is valid for issue creation.

  Args:
    cnxn: A connection object to use services with.
    services: An object containing services to use to look up relevant data.
    issues: A PB containing the issue to validate.
    description: The description for the issue.

  Raises:
    InputException if the issue is not valid.
  """
  project = services.project.GetProject(cnxn, issue.project_id)
  config = services.config.GetProjectConfig(cnxn, issue.project_id)

  with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
    owner_is_valid, owner_err_msg = IsValidIssueOwner(
        cnxn, project, issue.owner_id, services)
    if not owner_is_valid:
      err_agg.AddErrorMessage(owner_err_msg)
    if not issue.summary.strip():
      err_agg.AddErrorMessage('Summary is required')
    if not description.strip():
      err_agg.AddErrorMessage('Description is required')
    if len(issue.summary) > tracker_constants.MAX_SUMMARY_CHARS:
      err_agg.AddErrorMessage('Summary is too long')
    if len(description) > tracker_constants.MAX_COMMENT_CHARS:
      err_agg.AddErrorMessage('Description is too long')

    # Check all users exist. Owner already check by IsValidIssueOwner.
    all_users = [uid for uid in issue.cc_ids]
    for av in issue.approval_values:
      all_users.extend(av.approver_ids)
    field_users = [fv.user_id for fv in issue.field_values if fv.user_id]
    all_users.extend(field_users)
    AssertUsersExist(cnxn, services, all_users, err_agg)

    label_validity_error = field_helpers.ValidateLabels(
        cnxn, services, issue.project_id, issue.labels)
    if label_validity_error:
      err_agg.AddErrorMessage(label_validity_error)

    field_validity_errors = field_helpers.ValidateCustomFields(
        cnxn, services, issue.field_values, config, project, issue=issue)
    if field_validity_errors:
      err_agg.AddErrorMessage("\n".join(field_validity_errors))
    if not services.config.LookupStatusID(cnxn, issue.project_id, issue.status,
                                          autocreate=False):
      err_agg.AddErrorMessage('Undefined status: %s' % issue.status)
    all_comp_ids = {
        cd.component_id for cd in config.component_defs if not cd.deprecated
    }
    for comp_id in issue.component_ids:
      if comp_id not in all_comp_ids:
        err_agg.AddErrorMessage(
            'Undefined or deprecated component with id: %d' % comp_id)


def _ComputeNewCcsFromIssueMerge(merge_into_issue, source_issues):
  # type: (Issue, Collection[Issue]) -> Collection[int]
  """Compute ccs that should be added from source_issues to merge_into_issue."""

  merge_into_restrictions = permissions.GetRestrictions(merge_into_issue)
  new_cc_ids = set()
  for issue in source_issues:
    # We don't want to leak metadata like ccs of restricted issues.
    # So we don't merge ccs from restricted source issues, unless their
    # restrictions match the restrictions of the target.
    if permissions.HasRestrictions(issue, perm='View'):
      source_restrictions = permissions.GetRestrictions(issue)
      if (issue.project_id != merge_into_issue.project_id or
          set(source_restrictions) != set(merge_into_restrictions)):
        continue

    new_cc_ids.update(issue.cc_ids)
    if issue.owner_id:
      new_cc_ids.add(issue.owner_id)

  return [
      cc_id for cc_id in sorted(new_cc_ids)
      if cc_id not in merge_into_issue.cc_ids
  ]


def _EnforceNonMergeStatusDeltas(cnxn, issue_delta_pairs, services):
  # type: (MonorailConnection, Sequence[Tuple[Issue, IssueDelta]], Services)
  """Update deltas in RAM to remove merged if a MERGED status is removed."""
  project_ids = list(
      {issue.project_id for (issue, _delta) in issue_delta_pairs})
  configs_by_id = services.config.GetProjectConfigs(cnxn, project_ids)
  statuses_offer_merge_by_pid = {
      pid:
      [status.lower() for status in configs_by_id[pid].statuses_offer_merge]
      for pid in project_ids
  }

  for issue, delta in issue_delta_pairs:
    statuses_offer_merge = statuses_offer_merge_by_pid[issue.project_id]
    # Remove merged_into and merged_into_external when a status is moved
    # to a non-MERGED status ONLY if the delta does not have merged_into values
    # If delta does change merged_into values, the request will fail from
    # AssertIssueChangesValue().
    if (delta.status and delta.status.lower() not in statuses_offer_merge and
        delta.merged_into is None and delta.merged_into_external is None):
      if issue.merged_into:
        delta.merged_into = 0
      elif issue.merged_into_external:
        delta.merged_into_external = ''


class _IssueChangeImpactedIssues():
  """Class to track changes of issues impacted by updates to other issues."""

  def __init__(self):

    # Each of the dicts below should be used to track
    # {impacted_issue_id: [issues being modified that impact the keyed issue]}.

    # e.g. `blocking_remove` with {iid_1: [iid_2, iid_3]} means that
    # `TrackImpactedIssues` has been called with a delta of
    # IssueDelta(blocked_on_remove=[iid_1]) for both issue 2 and issue 3.
    self.blocking_add = collections.defaultdict(list)
    self.blocking_remove = collections.defaultdict(list)
    self.blocked_on_add = collections.defaultdict(list)
    self.blocked_on_remove = collections.defaultdict(list)
    self.merged_from_add = collections.defaultdict(list)
    self.merged_from_remove = collections.defaultdict(list)

  def ComputeAllImpactedIIDs(self):
    # type: () -> Collection[int]
    """Computes the unique set of all impacted issue ids."""
    return (
        set(self.blocking_add.keys()) | set(self.blocking_remove.keys())
        | set(self.blocked_on_add.keys()) | set(self.blocked_on_remove.keys())
        | set(self.merged_from_add.keys())
        | set(self.merged_from_remove.keys()))

  def TrackImpactedIssues(self, issue, delta):
    # type: (Issue, IssueDelta) -> None
    """Track impacted issues from when `delta` is applied to `issue`.

    Args:
      issue: Issue that the delta will be applied to, but has not yet.
      delta: IssueDelta representing the changes that will be made to
        the issue.
    """
    for impacted_iid in delta.blocked_on_add:
      self.blocking_add[impacted_iid].append(issue.issue_id)
    for impacted_iid in delta.blocked_on_remove:
      self.blocking_remove[impacted_iid].append(issue.issue_id)

    for impacted_iid in delta.blocking_add:
      self.blocked_on_add[impacted_iid].append(issue.issue_id)
    for impacted_iid in delta.blocking_remove:
      self.blocked_on_remove[impacted_iid].append(issue.issue_id)

    if (delta.merged_into == framework_constants.NO_ISSUE_SPECIFIED and
        issue.merged_into):
      self.merged_from_remove[issue.merged_into].append(issue.issue_id)
    elif delta.merged_into and issue.merged_into != delta.merged_into:
      self.merged_from_add[delta.merged_into].append(issue.issue_id)
      if issue.merged_into:
        self.merged_from_remove[issue.merged_into].append(issue.issue_id)

  def ApplyImpactedIssueChanges(self, cnxn, impacted_issue, services):
    # type: (MonorailConnection, Issue, Services) ->
    #     Tuple[Collection[Amendment], Sequence[int]]
    """Apply the tracked changes in RAM for the given impacted issue.

    Args:
      cnxn: connection to SQL database.
      impacted_issue: Issue PB that we are applying the changes to.
      services: Services used to fetch info from DB or cache.

    Returns:
      All the amendments that represent the changes applied to the issue
      and a list of the new issue starrers.

    Side-effect:
      The given impacted_issue will be updated in RAM.
    """
    issue_id = impacted_issue.issue_id

    # Process changes for blocking/blocked_on issue changes.
    amendments, _impacted_iids = tracker_bizobj.ApplyIssueBlockRelationChanges(
        cnxn, impacted_issue, self.blocked_on_add[issue_id],
        self.blocked_on_remove[issue_id], self.blocking_add[issue_id],
        self.blocking_remove[issue_id], services.issue)

    # Process changes in merged issues.
    merged_from_add = self.merged_from_add.get(issue_id, [])
    merged_from_remove = self.merged_from_remove.get(issue_id, [])

    # Merge ccs into impacted_issue from all merged issues,
    # compute new starrers, and set star_count.
    new_starrers = []
    if merged_from_add:
      issues_dict, _misses = services.issue.GetIssuesDict(cnxn, merged_from_add)
      merged_from_add_issues = issues_dict.values()
      new_cc_ids = _ComputeNewCcsFromIssueMerge(
          impacted_issue, merged_from_add_issues)
      if new_cc_ids:
        impacted_issue.cc_ids.extend(new_cc_ids)
        amendments.append(
            tracker_bizobj.MakeCcAmendment(new_cc_ids, []))
      new_starrers = list(
          GetNewIssueStarrers(cnxn, services, merged_from_add, issue_id))
      if new_starrers:
        impacted_issue.star_count += len(new_starrers)

    if merged_from_add or merged_from_remove:
      merged_from_add_refs = services.issue.LookupIssueRefs(
          cnxn, merged_from_add).values()
      merged_from_remove_refs = services.issue.LookupIssueRefs(
          cnxn, merged_from_remove).values()
      amendments.append(
          tracker_bizobj.MakeMergedIntoAmendment(
              merged_from_add_refs, merged_from_remove_refs,
              default_project_name=impacted_issue.project_name))
    return amendments, new_starrers
