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

"""Functions that convert protorpc business objects into protoc objects.

Monorail uses protorpc objects internally, whereas the API uses protoc
objects.  The difference is not just the choice of protobuf library, there
will always be a need for conversion because out internal objects may have
field that we do not want to expose externally, or the format of some fields
may be different than how we want to expose them.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging

from six import string_types

import settings
from api.api_proto import common_pb2
from api.api_proto import features_objects_pb2
from api.api_proto import issue_objects_pb2
from api.api_proto import project_objects_pb2
from api.api_proto import user_objects_pb2
from features import federated
from framework import exceptions
from framework import filecontent
from framework import framework_constants
from framework import framework_helpers
from framework import permissions
from framework import validate
from services import features_svc
from tracker import attachment_helpers
from tracker import field_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers
from proto import tracker_pb2
from proto import user_pb2


# Convert and ingest objects in issue_objects.proto.


def ConvertApprovalValues(approval_values, phases, users_by_id, config):
  """Convert a list of ApprovalValue into protoc Approvals."""
  phases_by_id = {
    phase.phase_id: phase
    for phase in phases}
  result = [
    ConvertApproval(
      av, users_by_id, config, phase=phases_by_id.get(av.phase_id))
    for av in approval_values]
  result = [av for av in result if av]
  return result


def ConvertApproval(approval_value, users_by_id, config, phase=None):
  """Use the given ApprovalValue to create a protoc Approval."""
  approval_name = ''
  fd = tracker_bizobj.FindFieldDefByID(approval_value.approval_id, config)
  if fd:
    approval_name = fd.field_name
  else:
    logging.info(
        'Ignoring approval value referencing a non-existing field: %r',
        approval_value)
    return None

  field_ref = ConvertFieldRef(
      approval_value.approval_id, approval_name,
      tracker_pb2.FieldTypes.APPROVAL_TYPE, None)
  approver_refs = ConvertUserRefs(approval_value.approver_ids, [], users_by_id,
                                  False)
  setter_ref = ConvertUserRef(approval_value.setter_id, None, users_by_id)

  status = ConvertApprovalStatus(approval_value.status)
  set_on = approval_value.set_on

  phase_ref = issue_objects_pb2.PhaseRef()
  if phase:
    phase_ref.phase_name = phase.name

  result = issue_objects_pb2.Approval(
      field_ref=field_ref, approver_refs=approver_refs,
      status=status, set_on=set_on, setter_ref=setter_ref,
      phase_ref=phase_ref)
  return result


def ConvertStatusRef(explicit_status, derived_status, config):
  """Use the given status strings to create a StatusRef."""
  status = explicit_status or derived_status
  is_derived = not explicit_status
  if not status:
    return common_pb2.StatusRef(
        status=framework_constants.NO_VALUES, is_derived=False, means_open=True)

  return common_pb2.StatusRef(
      status=status,
      is_derived=is_derived,
      means_open=tracker_helpers.MeansOpenInProject(status, config))


def ConvertApprovalStatus(status):
  """Use the given protorpc ApprovalStatus to create a protoc ApprovalStatus"""
  return issue_objects_pb2.ApprovalStatus.Value(status.name)


def ConvertUserRef(explicit_user_id, derived_user_id, users_by_id):
  """Use the given user IDs to create a UserRef."""
  user_id = explicit_user_id or derived_user_id
  is_derived = not explicit_user_id
  if not user_id:
    return None;

  return common_pb2.UserRef(
      user_id=user_id,
      is_derived=is_derived,
      display_name=users_by_id[user_id].display_name)

# TODO(jojwang): Rewrite method, ConvertUserRefs should be able to
# call ConvertUserRef
def ConvertUserRefs(explicit_user_ids, derived_user_ids, users_by_id,
                    use_email):
  # (List(int), List(int), Dict(int: UserView), bool) -> List(UserRef)
  """Use the given user ID lists to create a list of UserRef.

  Args:
    explicit_user_ids: list of user_ids for users that are not derived.
    derived_user_ids: list of user_ids for users derived from FilterRules.
    users_by_id: dict of {user_id: UserView, ...} for all users in
      explicit_user_ids and derived_user_ids.
    use_email: boolean true if the UserView.email should be used as
      the display_name instead of UserView.display_name, which may be obscured.

  Returns:
    A single list of UserRefs.
  """
  result = []
  for user_id in explicit_user_ids:
    result.append(common_pb2.UserRef(
      user_id=user_id,
      is_derived=False,
      display_name=(
          users_by_id[user_id].email
          if use_email
          else users_by_id[user_id].display_name)))
  for user_id in derived_user_ids:
    result.append(common_pb2.UserRef(
      user_id=user_id,
      is_derived=True,
      display_name=(
          users_by_id[user_id].email
          if use_email
          else users_by_id[user_id].display_name)))
  return result


def ConvertUsers(users, users_by_id):
  """Use the given protorpc Users to create protoc Users.

  Args:
    users: list of protorpc Users to convert.
    users_by_id: dict {user_id: UserView} of all Users linked
      from the users list.

  Returns:
    A list of protoc Users.
  """
  result = []
  for user in users:
    linked_parent_ref = None
    if user.linked_parent_id:
      linked_parent_ref = ConvertUserRefs(
          [user.linked_parent_id], [], users_by_id, False)[0]
    linked_child_refs = ConvertUserRefs(
        user.linked_child_ids, [], users_by_id, False)
    converted_user = user_objects_pb2.User(
        user_id=user.user_id,
        display_name=user.email,
        is_site_admin=user.is_site_admin,
        availability=framework_helpers.GetUserAvailability(user)[0],
        linked_parent_ref=linked_parent_ref,
        linked_child_refs=linked_child_refs)
    result.append(converted_user)
  return result


def ConvertPrefValues(userprefvalues):
  """Convert a list of protorpc UserPrefValue to protoc UserPrefValues."""
  return [
      user_objects_pb2.UserPrefValue(name=upv.name, value=upv.value)
      for upv in userprefvalues]


def ConvertLabels(explicit_labels, derived_labels):
  """Combine the given explicit and derived lists into LabelRefs."""
  explicit_refs = [common_pb2.LabelRef(label=lab, is_derived=False)
                   for lab in explicit_labels]
  derived_refs = [common_pb2.LabelRef(label=lab, is_derived=True)
                  for lab in derived_labels]
  return explicit_refs + derived_refs


def ConvertComponentRef(component_id, config, is_derived=False):
  """Make a ComponentRef from the component_id and project config."""
  component_def = tracker_bizobj.FindComponentDefByID(component_id, config)
  if not component_def:
    logging.info('Ignoring non-existing component id %s', component_id)
    return None
  result = common_pb2.ComponentRef(
      path=component_def.path,
      is_derived=is_derived)
  return result

# TODO(jojwang): rename to ConvertComponentRefs
def ConvertComponents(explicit_component_ids, derived_component_ids, config):
  """Make a ComponentRef for each component_id."""
  result = [ConvertComponentRef(cid, config) for cid in explicit_component_ids]
  result += [
      ConvertComponentRef(cid, config, is_derived=True)
      for cid in derived_component_ids]
  result = [cr for cr in result if cr]
  return result


def ConvertIssueRef(issue_ref_pair, ext_id=''):
  """Convert (project_name, local_id) to an IssueRef protoc object.

  With optional external ref in ext_id.
  """
  project_name, local_id = issue_ref_pair
  ref = common_pb2.IssueRef(project_name=project_name, local_id=local_id,
      ext_identifier=ext_id)
  return ref


def ConvertIssueRefs(issue_ids, related_refs_dict):
  """Convert a list of iids to IssueRef protoc objects."""
  return [ConvertIssueRef(related_refs_dict[iid]) for iid in issue_ids]


def ConvertFieldValue(field_id, field_name, value, field_type,
                      approval_name=None, phase_name=None, is_derived=False):
  """Convert one field value view item into a protoc FieldValue."""
  if not isinstance(value, string_types):
    value = str(value)
  fv = issue_objects_pb2.FieldValue(
      field_ref=ConvertFieldRef(field_id, field_name, field_type,
                                approval_name),
      value=value,
      is_derived=is_derived)
  if phase_name:
    fv.phase_ref.phase_name = phase_name

  return fv


def ConvertFieldType(field_type):
  """Use the given protorpc FieldTypes enum to create a protoc FieldType."""
  return common_pb2.FieldType.Value(field_type.name)


def ConvertFieldRef(field_id, field_name, field_type, approval_name):
  """Convert a field name and protorpc FieldType into a protoc FieldRef."""
  return common_pb2.FieldRef(field_id=field_id,
                             field_name=field_name,
                             type=ConvertFieldType(field_type),
                             approval_name=approval_name)


def ConvertFieldValues(
    config, labels, derived_labels, field_values, users_by_id, phases=None):
  """Convert lists of labels and field_values to protoc FieldValues."""
  fvs = []
  phase_names_by_id = {phase.phase_id: phase.name for phase in phases or []}
  fds_by_id = {fd.field_id:fd for fd in config.field_defs}
  fids_by_name = {fd.field_name:fd.field_id for fd in config.field_defs}
  enum_names_by_lower = {
      fd.field_name.lower(): fd.field_name for fd in config.field_defs
      if fd.field_type == tracker_pb2.FieldTypes.ENUM_TYPE}

  labels_by_prefix = tracker_bizobj.LabelsByPrefix(
      labels, list(enum_names_by_lower.keys()))
  der_labels_by_prefix = tracker_bizobj.LabelsByPrefix(
      derived_labels, list(enum_names_by_lower.keys()))

  for lower_field_name, values in labels_by_prefix.items():
    field_name = enum_names_by_lower.get(lower_field_name)
    if not field_name:
      continue
    fvs.extend(
        [ConvertFieldValue(
            fids_by_name.get(field_name), field_name, value,
            tracker_pb2.FieldTypes.ENUM_TYPE)
         for value in values])

  for lower_field_name, values in der_labels_by_prefix.items():
    field_name = enum_names_by_lower.get(lower_field_name)
    if not field_name:
      continue
    fvs.extend(
        [ConvertFieldValue(
            fids_by_name.get(field_name), field_name, value,
            tracker_pb2.FieldTypes.ENUM_TYPE, is_derived=True)
         for value in values])

  for fv in field_values:
    field_def = fds_by_id.get(fv.field_id)
    if not field_def:
      logging.info(
          'Ignoring field value referencing a non-existent field: %r', fv)
      continue

    value = tracker_bizobj.GetFieldValue(fv, users_by_id)
    field_name = field_def.field_name
    field_type = field_def.field_type
    approval_name = None

    if field_def.approval_id is not None:
      approval_def = fds_by_id.get(field_def.approval_id)
      if approval_def:
        approval_name = approval_def.field_name

    fvs.append(ConvertFieldValue(
        fv.field_id, field_name, value, field_type, approval_name=approval_name,
        phase_name=phase_names_by_id.get(fv.phase_id), is_derived=fv.derived))

  return fvs


def ConvertIssue(issue, users_by_id, related_refs, config):
  """Convert our protorpc Issue to a protoc Issue.

  Args:
    issue: protorpc issue used by monorail internally.
    users_by_id: dict {user_id: UserViews} for all users mentioned in issue.
    related_refs: dict {issue_id: (project_name, local_id)} of all blocked-on,
        blocking, or merged-into issues referenced from this issue, regardless
        of perms.
    config: ProjectIssueConfig for this issue.

  Returns: A protoc Issue object.
  """
  status_ref = ConvertStatusRef(issue.status, issue.derived_status, config)
  owner_ref = ConvertUserRef(
      issue.owner_id, issue.derived_owner_id, users_by_id)
  cc_refs = ConvertUserRefs(
      issue.cc_ids, issue.derived_cc_ids, users_by_id, False)
  labels, derived_labels = tracker_bizobj.ExplicitAndDerivedNonMaskedLabels(
      issue.labels, issue.derived_labels, config)
  label_refs = ConvertLabels(labels, derived_labels)
  component_refs = ConvertComponents(
      issue.component_ids, issue.derived_component_ids, config)
  blocked_on_issue_refs = ConvertIssueRefs(
      issue.blocked_on_iids, related_refs)
  dangling_blocked_on_refs = [
      ConvertIssueRef((dangling_issue.project, dangling_issue.issue_id),
          ext_id=dangling_issue.ext_issue_identifier)
      for dangling_issue in issue.dangling_blocked_on_refs]
  blocking_issue_refs = ConvertIssueRefs(
      issue.blocking_iids, related_refs)
  dangling_blocking_refs = [
      ConvertIssueRef((dangling_issue.project, dangling_issue.issue_id),
          ext_id=dangling_issue.ext_issue_identifier)
      for dangling_issue in issue.dangling_blocking_refs]
  merged_into_issue_ref = None
  if issue.merged_into:
    merged_into_issue_ref = ConvertIssueRef(related_refs[issue.merged_into])
  if issue.merged_into_external:
    merged_into_issue_ref = ConvertIssueRef((None, None),
        ext_id=issue.merged_into_external)

  field_values = ConvertFieldValues(
      config, issue.labels, issue.derived_labels,
      issue.field_values, users_by_id, phases=issue.phases)
  approval_values = ConvertApprovalValues(
      issue.approval_values, issue.phases, users_by_id, config)
  reporter_ref = ConvertUserRef(issue.reporter_id, None, users_by_id)
  phases = [ConvertPhaseDef(phase) for phase in issue.phases]
  result = issue_objects_pb2.Issue(
      project_name=issue.project_name, local_id=issue.local_id,
      summary=issue.summary, status_ref=status_ref, owner_ref=owner_ref,
      cc_refs=cc_refs, label_refs=label_refs, component_refs=component_refs,
      blocked_on_issue_refs=blocked_on_issue_refs,
      dangling_blocked_on_refs=dangling_blocked_on_refs,
      blocking_issue_refs=blocking_issue_refs,
      dangling_blocking_refs=dangling_blocking_refs,
      merged_into_issue_ref=merged_into_issue_ref, field_values=field_values,
      is_deleted=issue.deleted, reporter_ref=reporter_ref,
      opened_timestamp=issue.opened_timestamp,
      closed_timestamp=issue.closed_timestamp,
      modified_timestamp=issue.modified_timestamp,
      component_modified_timestamp=issue.component_modified_timestamp,
      status_modified_timestamp=issue.status_modified_timestamp,
      owner_modified_timestamp=issue.owner_modified_timestamp,
      star_count=issue.star_count, is_spam=issue.is_spam,
      approval_values=approval_values, phases=phases)

  # TODO(crbug.com/monorail/5857): Set attachment_count unconditionally
  # after the underlying source of negative attachment counts has been
  # resolved and database has been repaired.
  if issue.attachment_count >= 0:
    result.attachment_count = issue.attachment_count

  return result


def ConvertPhaseDef(phase):
  """Convert a protorpc Phase to a protoc PhaseDef."""
  phase_def = issue_objects_pb2.PhaseDef(
      phase_ref=issue_objects_pb2.PhaseRef(phase_name=phase.name),
      rank=phase.rank)
  return phase_def


def ConvertAmendment(amendment, users_by_id):
  """Convert a protorpc Amendment to a protoc Amendment."""
  field_name = tracker_bizobj.GetAmendmentFieldName(amendment)
  new_value = tracker_bizobj.AmendmentString(amendment, users_by_id)
  result = issue_objects_pb2.Amendment(
      field_name=field_name, new_or_delta_value=new_value,
      old_value=amendment.oldvalue)
  return result


def ConvertAttachment(attach, project_name):
  """Convert a protorpc Attachment to a protoc Attachment."""
  size, thumbnail_url, view_url, download_url = None, None, None, None
  if not attach.deleted:
    size = attach.filesize
    download_url = attachment_helpers.GetDownloadURL(attach.attachment_id)
    view_url = attachment_helpers.GetViewURL(attach, download_url, project_name)
    thumbnail_url = attachment_helpers.GetThumbnailURL(attach, download_url)

  result = issue_objects_pb2.Attachment(
      attachment_id=attach.attachment_id, filename=attach.filename,
      size=size, content_type=attach.mimetype,
      is_deleted=attach.deleted, thumbnail_url=thumbnail_url,
      view_url=view_url, download_url=download_url)
  return result


def ConvertComment(
    issue, comment, config, users_by_id, comment_reporters, description_nums,
    user_id, perms):
  """Convert a protorpc IssueComment to a protoc Comment."""
  commenter = users_by_id[comment.user_id]

  can_delete = permissions.CanDeleteComment(
      comment, commenter, user_id, perms)
  can_flag, is_flagged = permissions.CanFlagComment(
      comment, commenter, comment_reporters, user_id, perms)
  can_view = permissions.CanViewComment(
      comment, commenter, user_id, perms)
  can_view_inbound_message = permissions.CanViewInboundMessage(
      comment, user_id, perms)

  is_deleted = bool(comment.deleted_by or is_flagged or commenter.banned)

  result = issue_objects_pb2.Comment(
      project_name=issue.project_name,
      local_id=issue.local_id,
      sequence_num=comment.sequence,
      is_deleted=is_deleted,
      can_delete=can_delete,
      is_spam=is_flagged,
      can_flag=can_flag,
      timestamp=comment.timestamp)

  if can_view:
    result.commenter.CopyFrom(
        ConvertUserRef(comment.user_id, None, users_by_id))
    result.content = comment.content
    if comment.inbound_message and can_view_inbound_message:
      result.inbound_message = comment.inbound_message
    result.amendments.extend([
        ConvertAmendment(amend, users_by_id)
        for amend in comment.amendments])
    result.attachments.extend([
        ConvertAttachment(attach, issue.project_name)
        for attach in comment.attachments])

  if comment.id in description_nums:
    result.description_num = description_nums[comment.id]

  fd = tracker_bizobj.FindFieldDefByID(comment.approval_id, config)
  if fd:
    result.approval_ref.field_name = fd.field_name

  return result


def ConvertCommentList(
    issue, comments, config, users_by_id, comment_reporters, user_id, perms):
  """Convert a list of protorpc IssueComments to protoc Comments."""
  description_nums = {}
  for comment in comments:
    if (comment.is_description and not users_by_id[comment.user_id].banned and
        not comment.deleted_by and not comment.is_spam):
      description_nums[comment.id] = len(description_nums) + 1

  result = [
    ConvertComment(
       issue, c, config, users_by_id, comment_reporters.get(c.id, []),
       description_nums, user_id, perms)
    for c in comments]
  return result


def IngestUserRef(cnxn, user_ref, user_service, autocreate=False):
  """Return ID of specified user or raise NoSuchUserException."""
  try:
    return IngestUserRefs(
        cnxn, [user_ref], user_service, autocreate=autocreate)[0]
  except IndexError:
    # user_ref.display_name was not a valid email.
    raise exceptions.NoSuchUserException


def IngestUserRefs(cnxn, user_refs, user_service, autocreate=False):
  """Return IDs of specified users or raise NoSuchUserException."""

  # Filter out user_refs with invalid display_names.
  # Invalid emails won't get auto-created in LookupUserIds, but un-specified
  # user_ref.user_id values have the zero-value 0. So invalid user_ref's
  # need to be filtered out here to prevent these resulting in '0's in
  # the 'result' array.
  if autocreate:
    user_refs = [user_ref for user_ref in user_refs
                 if (not user_ref.display_name) or
                 validate.IsValidEmail(user_ref.display_name)]

  # 1. Verify that all specified user IDs actually match existing users.
  user_ids_to_verify = [user_ref.user_id for user_ref in user_refs
                        if user_ref.user_id]
  user_service.LookupUserEmails(cnxn, user_ids_to_verify)

  # 2. Lookup or create any users that are specified by email address.
  needed_emails = [user_ref.display_name for user_ref in user_refs
                   if not user_ref.user_id and user_ref.display_name]
  emails_to_ids = user_service.LookupUserIDs(
      cnxn, needed_emails, autocreate=autocreate)

  # 3. Build the result from emails_to_ids or straight from user_ref's
  # user_id.
  # Note: user_id can be specified as 0 to clear the issue owner.
  result = [
      emails_to_ids.get(user_ref.display_name.lower(), user_ref.user_id)
      for user_ref in user_refs
  ]
  return result


def IngestPrefValues(pref_values):
  """Return protorpc UserPrefValues for the given values."""
  return [user_pb2.UserPrefValue(name=upv.name, value=upv.value)
          for upv in pref_values]


def IngestComponentRefs(comp_refs, config, ignore_missing_objects=False):
  """Return IDs of specified components or raise NoSuchComponentException."""
  cids_by_path = {cd.path.lower(): cd.component_id
                  for cd in config.component_defs}
  result = []
  for comp_ref in comp_refs:
    cid = cids_by_path.get(comp_ref.path.lower())
    if cid:
      result.append(cid)
    else:
      if not ignore_missing_objects:
        raise exceptions.NoSuchComponentException()
  return result


def IngestFieldRefs(field_refs, config):
  """Return IDs of specified fields or raise NoSuchFieldDefException."""
  fids_by_name = {fd.field_name.lower(): fd.field_id
                  for fd in config.field_defs}
  result = []
  for field_ref in field_refs:
    fid = fids_by_name.get(field_ref.field_name.lower())
    if fid:
      result.append(fid)
    else:
      raise exceptions.NoSuchFieldDefException()
  return result


def IngestIssueRefs(cnxn, issue_refs, services):
  """Look up issue IDs for the specified issues."""
  project_names = set(ref.project_name for ref in issue_refs)
  project_names_to_id = services.project.LookupProjectIDs(cnxn, project_names)
  project_local_id_pairs = []
  for ref in issue_refs:
    if ref.ext_identifier:
      # TODO(jeffcarp): For external tracker refs, once we have the classes
      # set up, validate that the tracker for this specific ref is supported
      # and store the external ref in the issue properly.
      if '/' not in ref.ext_identifier:
        raise exceptions.InvalidExternalIssueReference()
      continue
    if ref.project_name in project_names_to_id:
      pair = (project_names_to_id[ref.project_name], ref.local_id)
      project_local_id_pairs.append(pair)
    else:
      raise exceptions.NoSuchProjectException()
  issue_ids, misses = services.issue.LookupIssueIDs(
      cnxn, project_local_id_pairs)
  if misses:
    raise exceptions.NoSuchIssueException()
  return issue_ids


def IngestExtIssueRefs(issue_refs):
  """Validate and return external issue refs."""
  return [
      ref.ext_identifier
      for ref in issue_refs
      if ref.ext_identifier
      and federated.IsShortlinkValid(ref.ext_identifier)]


def IngestIssueDelta(
    cnxn, services, delta, config, phases, ignore_missing_objects=False):
  """Ingest a protoc IssueDelta and create a protorpc IssueDelta."""
  status = None
  if delta.HasField('status'):
    status = delta.status.value
  owner_id = None
  if delta.HasField('owner_ref'):
    try:
      owner_id = IngestUserRef(cnxn, delta.owner_ref, services.user)
    except exceptions.NoSuchUserException as e:
      if not ignore_missing_objects:
        raise e
  summary = None
  if delta.HasField('summary'):
    summary = delta.summary.value

  cc_ids_add = IngestUserRefs(
      cnxn, delta.cc_refs_add, services.user, autocreate=True)
  cc_ids_remove = IngestUserRefs(cnxn, delta.cc_refs_remove, services.user)

  comp_ids_add = IngestComponentRefs(
      delta.comp_refs_add, config,
      ignore_missing_objects=ignore_missing_objects)
  comp_ids_remove = IngestComponentRefs(
      delta.comp_refs_remove, config,
      ignore_missing_objects=ignore_missing_objects)

  labels_add = [lab_ref.label for lab_ref in delta.label_refs_add]
  labels_remove = [lab_ref.label for lab_ref in delta.label_refs_remove]

  field_vals_add, field_vals_remove = _RedistributeEnumFieldsIntoLabels(
      labels_add, labels_remove,
      delta.field_vals_add, delta.field_vals_remove,
      config)

  field_vals_add = IngestFieldValues(
      cnxn, services.user, field_vals_add, config, phases=phases)
  field_vals_remove = IngestFieldValues(
      cnxn, services.user, field_vals_remove, config, phases=phases)
  fields_clear = IngestFieldRefs(delta.fields_clear, config)

  # Ingest intra-tracker issue refs.
  blocked_on_add = IngestIssueRefs(
      cnxn, delta.blocked_on_refs_add, services)
  blocked_on_remove = IngestIssueRefs(
      cnxn, delta.blocked_on_refs_remove, services)
  blocking_add = IngestIssueRefs(
      cnxn, delta.blocking_refs_add, services)
  blocking_remove = IngestIssueRefs(
      cnxn, delta.blocking_refs_remove, services)

  # Ingest inter-tracker issue refs.
  ext_blocked_on_add = IngestExtIssueRefs(delta.blocked_on_refs_add)
  ext_blocked_on_remove = IngestExtIssueRefs(delta.blocked_on_refs_remove)
  ext_blocking_add = IngestExtIssueRefs(delta.blocking_refs_add)
  ext_blocking_remove = IngestExtIssueRefs(delta.blocking_refs_remove)

  merged_into = None
  merged_into_external = None
  if delta.HasField('merged_into_ref'):
    if delta.merged_into_ref.ext_identifier:  # Adding an external merged.
      merged_into_external = delta.merged_into_ref.ext_identifier
    elif not delta.merged_into_ref.local_id:  # Clearing an internal merged.
      merged_into = 0
    else:  # Adding an internal merged.
      merged_into = IngestIssueRefs(cnxn, [delta.merged_into_ref], services)[0]

  result = tracker_bizobj.MakeIssueDelta(
      status, owner_id, cc_ids_add, cc_ids_remove, comp_ids_add,
      comp_ids_remove, labels_add, labels_remove, field_vals_add,
      field_vals_remove, fields_clear, blocked_on_add, blocked_on_remove,
      blocking_add, blocking_remove, merged_into, summary,
      ext_blocked_on_add=ext_blocked_on_add,
      ext_blocked_on_remove=ext_blocked_on_remove,
      ext_blocking_add=ext_blocking_add,
      ext_blocking_remove=ext_blocking_remove,
      merged_into_external=merged_into_external)
  return result

def IngestAttachmentUploads(attachment_uploads):
  """Ingest protoc AttachmentUpload objects as tuples."""
  result = []
  for up in attachment_uploads:
    if not up.filename:
      raise exceptions.InputException('Missing attachment name')
    if not up.content:
      raise exceptions.InputException('Missing attachment content')
    mimetype = filecontent.GuessContentTypeFromFilename(up.filename)
    attachment_tuple = (up.filename, up.content, mimetype)
    result.append(attachment_tuple)
  return result


def IngestApprovalDelta(cnxn, user_service, approval_delta, setter_id, config):
  """Ingest a protoc ApprovalDelta and create a protorpc ApprovalDelta."""
  fids_by_name = {fd.field_name.lower(): fd.field_id for
                       fd in config.field_defs}

  approver_ids_add = IngestUserRefs(
      cnxn, approval_delta.approver_refs_add, user_service, autocreate=True)
  approver_ids_remove = IngestUserRefs(
      cnxn, approval_delta.approver_refs_remove, user_service, autocreate=True)

  labels_add, labels_remove = [], []
  # TODO(jojwang): monorail:4673, validate enum values all belong to approval.
  field_vals_add, field_vals_remove = _RedistributeEnumFieldsIntoLabels(
      labels_add, labels_remove,
      approval_delta.field_vals_add, approval_delta.field_vals_remove,
      config)

  sub_fvs_add = IngestFieldValues(cnxn, user_service, field_vals_add, config)
  sub_fvs_remove = IngestFieldValues(
      cnxn, user_service, field_vals_remove, config)
  sub_fields_clear = [fids_by_name.get(clear.field_name.lower()) for
                      clear in approval_delta.fields_clear
                      if clear.field_name.lower() in fids_by_name]

  # protoc ENUMs default to the zero value (in this case: NOT_SET).
  # NOT_SET should only be allowed when an issue is first created.
  # Once a user changes it to something else, no one should be allowed
  # to set it back.
  status = None
  if approval_delta.status != issue_objects_pb2.NOT_SET:
    status = IngestApprovalStatus(approval_delta.status)

  return tracker_bizobj.MakeApprovalDelta(
      status, setter_id, approver_ids_add, approver_ids_remove,
      sub_fvs_add, sub_fvs_remove, sub_fields_clear, labels_add, labels_remove)


def IngestApprovalStatus(approval_status):
  """Ingest a protoc ApprovalStatus and create a protorpc ApprovalStatus. """
  if approval_status == issue_objects_pb2.NOT_SET:
    return tracker_pb2.ApprovalStatus.NOT_SET
  return tracker_pb2.ApprovalStatus(approval_status)


def IngestFieldValues(cnxn, user_service, field_values, config, phases=None):
  """Ingest a list of protoc FieldValues and create protorpc FieldValues.

  Args:
    cnxn: connection to the DB.
    user_service: interface to user data storage.
    field_values: a list of protoc FieldValue used by the API.
    config: ProjectIssueConfig for this field_value's project.
    phases: a list of the issue's protorpc Phases.


  Returns: A protorpc FieldValue object.
  """
  fds_by_name = {fd.field_name.lower(): fd for fd in config.field_defs}
  phases_by_name = {phase.name: phase.phase_id for phase in phases or []}

  ingested_fvs = []
  for fv in field_values:
    fd = fds_by_name.get(fv.field_ref.field_name.lower())
    if fd:
      if not fv.value:
        logging.info('Ignoring blank field value: %r', fv)
        continue
      ingested_fv = field_helpers.ParseOneFieldValue(
          cnxn, user_service, fd, fv.value)
      if not ingested_fv:
        raise exceptions.InputException(
          'Unparsable value for field %s' % fv.field_ref.field_name)
      if ingested_fv.user_id == field_helpers.INVALID_USER_ID:
        raise exceptions.NoSuchUserException()
      if fd.is_phase_field:
        ingested_fv.phase_id = phases_by_name.get(fv.phase_ref.phase_name)
      ingested_fvs.append(ingested_fv)

  return ingested_fvs


def IngestSavedQueries(cnxn, project_service, saved_queries):
  """Ingest a list of protoc SavedQuery and create protorpc SavedQuery.

  Args:
    cnxn: connection to the DB.
    project_service: interface to project data storage.
    saved_queries: a list of protoc Savedquery.

  Returns: A protorpc SavedQuery object.
  """
  if not saved_queries:
    return []

  project_ids = set()
  for sq in saved_queries:
    project_ids.update(sq.executes_in_project_ids)

  project_name_dict = project_service.LookupProjectNames(cnxn,
      project_ids)
  return [
      common_pb2.SavedQuery(
          query_id=sq.query_id,
          name=sq.name,
          query=sq.query,
          project_names=[project_name_dict[project_id]
              for project_id in sq.executes_in_project_ids]
      )
      for sq in saved_queries]


def IngestHotlistRefs(cnxn, user_service, features_service, hotlist_refs):
  return [IngestHotlistRef(cnxn, user_service, features_service, hotlist_ref)
        for hotlist_ref in hotlist_refs]


def IngestHotlistRef(cnxn, user_service, features_service, hotlist_ref):
  hotlist_id = None

  if hotlist_ref.hotlist_id:
    # If a hotlist ID was specified, verify it actually match existing hotlists.
    features_service.GetHotlist(cnxn, hotlist_ref.hotlist_id)
    hotlist_id = hotlist_ref.hotlist_id

  if hotlist_ref.name and hotlist_ref.owner:
    name = hotlist_ref.name
    owner_id = IngestUserRef(cnxn, hotlist_ref.owner, user_service)
    hotlists = features_service.LookupHotlistIDs(cnxn, [name], [owner_id])
    # Verify there is a hotlist with that name and owner.
    if (name.lower(), owner_id) not in hotlists:
      raise features_svc.NoSuchHotlistException()
    found_id = hotlists[name.lower(), owner_id]
    # If a hotlist_id was also given, verify it correspond to the name and
    # owner.
    if hotlist_id is not None and found_id != hotlist_id:
      raise features_svc.NoSuchHotlistException()
    hotlist_id = found_id

  # Neither an ID, nor a name-owner ref were given.
  if hotlist_id is None:
    raise features_svc.NoSuchHotlistException()

  return hotlist_id


def IngestPagination(pagination):
  max_items = settings.max_artifact_search_results_per_page
  if pagination.max_items:
    max_items = min(max_items, pagination.max_items)
  return pagination.start, max_items

# Convert and ingest objects in project_objects.proto.

def ConvertStatusDef(status_def):
  """Convert a protorpc StatusDef into a protoc StatusDef."""
  result = project_objects_pb2.StatusDef(
      status=status_def.status,
      means_open=status_def.means_open,
      docstring=status_def.status_docstring,
      deprecated=status_def.deprecated)
  return result


def ConvertLabelDef(label_def):
  """Convert a protorpc LabelDef into a protoc LabelDef."""
  result = project_objects_pb2.LabelDef(
      label=label_def.label,
      docstring=label_def.label_docstring,
      deprecated=label_def.deprecated)
  return result


def ConvertComponentDef(
  component_def, users_by_id, labels_by_id, include_admin_info):
  """Convert a protorpc ComponentDef into a protoc ComponentDef."""
  if not include_admin_info:
    return project_objects_pb2.ComponentDef(
        path=component_def.path,
        docstring=component_def.docstring,
        deprecated=component_def.deprecated)

  admin_refs = ConvertUserRefs(component_def.admin_ids, [], users_by_id, False)
  cc_refs = ConvertUserRefs(component_def.cc_ids, [], users_by_id, False)
  labels = [labels_by_id[lid] for lid in component_def.label_ids]
  label_refs = ConvertLabels(labels, [])
  creator_ref = ConvertUserRef(component_def.creator_id, None, users_by_id)
  modifier_ref = ConvertUserRef(component_def.modifier_id, None, users_by_id)
  return project_objects_pb2.ComponentDef(
      path=component_def.path,
      docstring=component_def.docstring,
      admin_refs=admin_refs,
      cc_refs=cc_refs,
      deprecated=component_def.deprecated,
      created=component_def.created,
      creator_ref=creator_ref,
      modified=component_def.modified,
      modifier_ref=modifier_ref,
      label_refs=label_refs)


def ConvertFieldDef(field_def, user_choices, users_by_id, config,
                    include_admin_info):
  """Convert a protorpc FieldDef into a protoc FieldDef."""
  parent_approval_name = None
  if field_def.approval_id:
    parent_fd = tracker_bizobj.FindFieldDefByID(field_def.approval_id, config)
    if parent_fd:
      parent_approval_name = parent_fd.field_name
  field_ref = ConvertFieldRef(
      field_def.field_id, field_def.field_name, field_def.field_type,
      parent_approval_name)

  enum_choices = []
  if field_def.field_type == tracker_pb2.FieldTypes.ENUM_TYPE:
    masked_labels = tracker_helpers.LabelsMaskedByFields(
        config, [field_def.field_name], True)
    enum_choices = [
        project_objects_pb2.LabelDef(
            label=label.name,
            docstring=label.docstring,
            deprecated=(label.commented == '#'))
        for label in masked_labels]

  if not include_admin_info:
    return project_objects_pb2.FieldDef(
        field_ref=field_ref,
        docstring=field_def.docstring,
        # Display full email address for user choices.
        user_choices=ConvertUserRefs(user_choices, [], users_by_id, True),
        enum_choices=enum_choices)

  admin_refs = ConvertUserRefs(field_def.admin_ids, [], users_by_id, False)
  # TODO(jrobbins): validation, permission granting, and notification options.

  return project_objects_pb2.FieldDef(
      field_ref=field_ref,
      applicable_type=field_def.applicable_type,
      is_required=field_def.is_required,
      is_niche=field_def.is_niche,
      is_multivalued=field_def.is_multivalued,
      docstring=field_def.docstring,
      admin_refs=admin_refs,
      is_phase_field=field_def.is_phase_field,
      enum_choices=enum_choices)


def ConvertApprovalDef(approval_def, users_by_id, config, include_admin_info):
  """Convert a protorpc ApprovalDef into a protoc ApprovalDef."""
  field_def = tracker_bizobj.FindFieldDefByID(approval_def.approval_id, config)
  field_ref = ConvertFieldRef(field_def.field_id, field_def.field_name,
                              field_def.field_type, None)
  if not include_admin_info:
    return project_objects_pb2.ApprovalDef(field_ref=field_ref)

  approver_refs = ConvertUserRefs(approval_def.approver_ids, [], users_by_id,
                                  False)
  return project_objects_pb2.ApprovalDef(
      field_ref=field_ref,
      approver_refs=approver_refs,
      survey=approval_def.survey)


def ConvertConfig(
    project, config, users_by_id, labels_by_id):
  """Convert a protorpc ProjectIssueConfig into a protoc Config."""
  status_defs = [
      ConvertStatusDef(sd)
      for sd in config.well_known_statuses]
  statuses_offer_merge = [
      ConvertStatusRef(sd.status, None, config)
      for sd in config.well_known_statuses
      if sd.status in config.statuses_offer_merge]
  label_defs = [
      ConvertLabelDef(ld)
      for ld in config.well_known_labels]
  component_defs = [
      ConvertComponentDef(
          cd, users_by_id, labels_by_id, True)
      for cd in config.component_defs]
  field_defs = [
      ConvertFieldDef(fd, [], users_by_id, config, True)
      for fd in config.field_defs
      if not fd.is_deleted]
  approval_defs = [
      ConvertApprovalDef(ad, users_by_id, config, True)
      for ad in config.approval_defs]
  result = project_objects_pb2.Config(
      project_name=project.project_name,
      status_defs=status_defs,
      statuses_offer_merge=statuses_offer_merge,
      label_defs=label_defs,
      exclusive_label_prefixes=config.exclusive_label_prefixes,
      component_defs=component_defs,
      field_defs=field_defs,
      approval_defs=approval_defs,
      restrict_to_known=config.restrict_to_known)
  return result


def ConvertProjectTemplateDefs(templates, users_by_id, config):
  """Convert a project's protorpc TemplateDefs into protoc TemplateDefs."""
  converted_templates = []
  for template in templates:
    owner_ref = ConvertUserRef(template.owner_id, None, users_by_id)
    status_ref = ConvertStatusRef(template.status, None, config)
    labels, _derived_labels = tracker_bizobj.ExplicitAndDerivedNonMaskedLabels(
        template.labels, [], config)
    label_refs = ConvertLabels(labels, [])
    admin_refs = ConvertUserRefs(template.admin_ids, [], users_by_id, False)
    field_values = ConvertFieldValues(
        config, template.labels, [], template.field_values, users_by_id,
        phases=template.phases)
    component_refs = ConvertComponents(template.component_ids, [], config)
    approval_values = ConvertApprovalValues(
        template.approval_values, template.phases, users_by_id, config)
    phases = [ConvertPhaseDef(phase) for phase in template.phases]

    converted_templates.append(
        project_objects_pb2.TemplateDef(
            template_name=template.name, content=template.content,
            summary=template.summary,
            summary_must_be_edited=template.summary_must_be_edited,
            owner_ref=owner_ref, status_ref=status_ref, label_refs=label_refs,
            members_only=template.members_only,
            owner_defaults_to_member=template.owner_defaults_to_member,
            admin_refs=admin_refs, field_values=field_values,
            component_refs=component_refs,
            component_required=template.component_required,
            approval_values=approval_values, phases=phases)
    )
  return converted_templates


def ConvertHotlist(hotlist, users_by_id):
  """Convert a protorpc Hotlist into a protoc Hotlist."""
  owner_ref = ConvertUserRef(
      hotlist.owner_ids[0], None, users_by_id)
  editor_refs = ConvertUserRefs(hotlist.editor_ids, [], users_by_id, False)
  follower_refs = ConvertUserRefs(
      hotlist.follower_ids, [], users_by_id, False)
  result = features_objects_pb2.Hotlist(
      owner_ref=owner_ref,
      editor_refs=editor_refs,
      follower_refs=follower_refs,
      name=hotlist.name,
      summary=hotlist.summary,
      description=hotlist.description,
      default_col_spec=hotlist.default_col_spec,
      is_private=hotlist.is_private,
  )
  return result


def ConvertHotlistItems(hotlist_items, issues_by_id, users_by_id, related_refs,
                        harmonized_config):
  # Note: hotlist_items are not always sorted by 'rank'
  sorted_ranks = sorted(item.rank for item in hotlist_items)
  friendly_ranks_dict = {
      rank: friendly_rank for friendly_rank, rank in
      enumerate(sorted_ranks, 1)}
  converted_items = []
  for item in hotlist_items:
    issue_pb = issues_by_id[item.issue_id]
    issue = ConvertIssue(
        issue_pb, users_by_id, related_refs, harmonized_config)
    adder_ref = ConvertUserRef(item.adder_id, None, users_by_id)
    converted_items.append(features_objects_pb2.HotlistItem(
        issue=issue,
        rank=friendly_ranks_dict[item.rank],
        adder_ref=adder_ref,
        added_timestamp=item.date_added,
        note=item.note))
  return converted_items


def ConvertValueAndWhy(value_and_why):
  return common_pb2.ValueAndWhy(
      value=value_and_why.get('value'),
      why=value_and_why.get('why'))


def ConvertValueAndWhyList(value_and_why_list):
  return [ConvertValueAndWhy(vnw) for vnw in value_and_why_list]


def _RedistributeEnumFieldsIntoLabels(
    labels_add, labels_remove, field_vals_add, field_vals_remove, config):
  """Look at the custom field values and treat enum fields as labels.

  Args:
    labels_add: list of labels to add/set on the issue.
    labels_remove: list of labels to remove from the issue.
    field_val_add: list of protoc FieldValues to be added.
    field_val_remove: list of protoc FieldValues to be removed.
        remove.
    config: ProjectIssueConfig PB including custom field definitions.

  Returns:
    Two revised lists of protoc FieldValues to be added and removed,
      without enum_types.

  SIDE-EFFECT: the labels and labels_remove lists will be extended with
  key-value labels corresponding to the enum field values.
  """
  field_val_strs_add = {}
  for field_val in field_vals_add:
    field_val_strs_add.setdefault(field_val.field_ref.field_id, []).append(
        field_val.value)

  field_val_strs_remove = {}
  for field_val in field_vals_remove:
    field_val_strs_remove.setdefault(field_val.field_ref.field_id, []).append(
        field_val.value)

  field_helpers.ShiftEnumFieldsIntoLabels(
      labels_add, labels_remove, field_val_strs_add, field_val_strs_remove,
      config)

  # Filter out the fields that were shifted into labels
  updated_field_vals_add = [
      fv for fv in field_vals_add
      if fv.field_ref.field_id in field_val_strs_add]
  updated_field_vals_remove = [
      fv for fv in field_vals_remove
      if fv.field_ref.field_id in field_val_strs_remove]

  return updated_field_vals_add, updated_field_vals_remove
