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

"""Convert Monorail PB objects to API PB objects"""

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

import datetime
import logging
import time

from six import string_types

from businesslogic import work_env
from framework import exceptions
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import permissions
from framework import timestr
from mrproto import api_pb2_v1
from mrproto import project_pb2
from mrproto import tracker_pb2
from services import project_svc
from tracker import field_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers


def convert_project(project, config, role, templates):
  """Convert Monorail Project PB to API ProjectWrapper PB."""

  return api_pb2_v1.ProjectWrapper(
      kind='monorail#project',
      name=project.project_name,
      externalId=project.project_name,
      htmlLink='/p/%s/' % project.project_name,
      summary=project.summary,
      description=project.description,
      role=role,
      issuesConfig=convert_project_config(config, templates))


def convert_project_config(config, templates):
  """Convert Monorail ProjectIssueConfig PB to API ProjectIssueConfig PB."""

  return api_pb2_v1.ProjectIssueConfig(
      kind='monorail#projectIssueConfig',
      restrictToKnown=config.restrict_to_known,
      defaultColumns=config.default_col_spec.split(),
      defaultSorting=config.default_sort_spec.split(),
      statuses=[convert_status(s) for s in config.well_known_statuses],
      labels=[convert_label(l) for l in config.well_known_labels],
      prompts=[convert_template(t) for t in templates],
      defaultPromptForMembers=config.default_template_for_developers,
      defaultPromptForNonMembers=config.default_template_for_users)


def convert_status(status):
  """Convert Monorail StatusDef PB to API Status PB."""

  return api_pb2_v1.Status(
      status=status.status,
      meansOpen=status.means_open,
      description=status.status_docstring)


def convert_label(label):
  """Convert Monorail LabelDef PB to API Label PB."""

  return api_pb2_v1.Label(
      label=label.label,
      description=label.label_docstring)


def convert_template(template):
  """Convert Monorail TemplateDef PB to API Prompt PB."""

  return api_pb2_v1.Prompt(
      name=template.name,
      title=template.summary,
      description=template.content,
      titleMustBeEdited=template.summary_must_be_edited,
      status=template.status,
      labels=template.labels,
      membersOnly=template.members_only,
      defaultToMember=template.owner_defaults_to_member,
      componentRequired=template.component_required)


def convert_person(user_id, cnxn, services, trap_exception=False):
  """Convert user id to API AtomPerson PB or None if user_id is None."""

  if not user_id:
    # convert_person should handle 'converting' optional user values,
    # like issue.owner, where user_id may be None.
    return None
  if user_id == framework_constants.DELETED_USER_ID:
    return api_pb2_v1.AtomPerson(
        kind='monorail#issuePerson',
        name=framework_constants.DELETED_USER_NAME)
  try:
    user = services.user.GetUser(cnxn, user_id)
  except exceptions.NoSuchUserException as ex:
    if trap_exception:
      logging.warning(str(ex))
      return None
    else:
      raise ex

  days_ago = None
  if user.last_visit_timestamp:
    secs_ago = int(time.time()) - user.last_visit_timestamp
    days_ago = secs_ago // framework_constants.SECS_PER_DAY
  return api_pb2_v1.AtomPerson(
      kind='monorail#issuePerson',
      name=user.email,
      htmlLink='https://%s/u/%d' % (framework_helpers.GetHostPort(), user_id),
      last_visit_days_ago=days_ago,
      email_bouncing=bool(user.email_bounce_timestamp),
      vacation_message=user.vacation_message)


def convert_issue_ids(issue_ids, mar, services):
  """Convert global issue ids to API IssueRef PB."""

  # missed issue ids are filtered out.
  issues = services.issue.GetIssues(mar.cnxn, issue_ids)
  result = []
  for issue in issues:
    issue_ref = api_pb2_v1.IssueRef(
      issueId=issue.local_id,
      projectId=issue.project_name,
      kind='monorail#issueRef')
    result.append(issue_ref)
  return result


def convert_issueref_pbs(issueref_pbs, mar, services):
  """Convert API IssueRef PBs to global issue ids."""

  if issueref_pbs:
    result = []
    for ir in issueref_pbs:
      project_id = mar.project_id
      if ir.projectId:
        project = services.project.GetProjectByName(
          mar.cnxn, ir.projectId)
        if project:
          project_id = project.project_id
      try:
        issue = services.issue.GetIssueByLocalID(
            mar.cnxn, project_id, ir.issueId)
        result.append(issue.issue_id)
      except exceptions.NoSuchIssueException:
        logging.warning(
            'Issue (%s:%d) does not exist.' % (ir.projectId, ir.issueId))
    return result
  else:
    return None


def convert_approvals(cnxn, approval_values, services, config, phases):
  """Convert an Issue's Monorail ApprovalValue PBs to API Approval"""
  fds_by_id = {fd.field_id: fd for fd in config.field_defs}
  phases_by_id = {phase.phase_id: phase for phase in phases}
  approvals = []
  for av in approval_values:
    approval_fd = fds_by_id.get(av.approval_id)
    if approval_fd is None:
      logging.warning(
          'Approval (%d) does not exist' % av.approval_id)
      continue
    if approval_fd.field_type is not tracker_pb2.FieldTypes.APPROVAL_TYPE:
      logging.warning(
          'field %s has unexpected field_type: %s' % (
              approval_fd.field_name, approval_fd.field_type.name))
      continue

    approval = api_pb2_v1.Approval()
    approval.approvalName = approval_fd.field_name
    approvers = [convert_person(approver_id, cnxn, services)
                 for approver_id in av.approver_ids]
    approval.approvers = [approver for approver in approvers if approver]

    approval.status = api_pb2_v1.ApprovalStatus(av.status.number)
    if av.setter_id:
      approval.setter = convert_person(av.setter_id, cnxn, services)
    if av.set_on:
      approval.setOn = datetime.datetime.fromtimestamp(av.set_on)
    if av.phase_id:
      try:
        approval.phaseName = phases_by_id[av.phase_id].name
      except KeyError:
        logging.warning('phase %d not found in given phases list' % av.phase_id)
    approvals.append(approval)
  return approvals


def convert_phases(phases):
  """Convert an Issue's Monorail Phase PBs to API Phase."""
  converted_phases = []
  for idx, phase in enumerate(phases):
    if not phase.name:
      try:
        logging.warning(
            'Phase %d has no name, skipping conversion.' % phase.phase_id)
      except TypeError:
        logging.warning(
            'Phase #%d (%s) has no name or id, skipping conversion.' % (
                idx, phase))
      continue
    converted = api_pb2_v1.Phase(phaseName=phase.name, rank=phase.rank)
    converted_phases.append(converted)
  return converted_phases


def convert_issue(cls, issue, mar, services, migrated_id=None):
  """Convert Monorail Issue PB to API IssuesGetInsertResponse."""

  config = services.config.GetProjectConfig(mar.cnxn, issue.project_id)
  granted_perms = tracker_bizobj.GetGrantedPerms(
      issue, mar.auth.effective_ids, config)
  issue_project = services.project.GetProject(mar.cnxn, issue.project_id)
  component_list = []
  for cd in config.component_defs:
    cid = cd.component_id
    if cid in issue.component_ids:
      component_list.append(cd.path)
  cc_list = [convert_person(p, mar.cnxn, services) for p in issue.cc_ids]
  cc_list = [p for p in cc_list if p is not None]
  field_values_list = []
  fds_by_id = {
      fd.field_id: fd for fd in config.field_defs}
  phases_by_id = {phase.phase_id: phase for phase in issue.phases}
  for fv in issue.field_values:
    fd = fds_by_id.get(fv.field_id)
    if not fd:
      logging.warning('Custom field %d of project %s does not exist',
                      fv.field_id, issue_project.project_name)
      continue
    val = None
    if fv.user_id:
      val = _get_user_email(
          services.user, mar.cnxn, fv.user_id)
    else:
      val = tracker_bizobj.GetFieldValue(fv, {})
      if not isinstance(val, string_types):
        val = str(val)
    new_fv = api_pb2_v1.FieldValue(
        fieldName=fd.field_name,
        fieldValue=val,
        derived=fv.derived)
    if fd.approval_id:  # Attach parent approval name
      approval_fd = fds_by_id.get(fd.approval_id)
      if not approval_fd:
        logging.warning('Parent approval field %d of field %s does not exist',
                        fd.approval_id, fd.field_name)
      else:
        new_fv.approvalName = approval_fd.field_name
    elif fv.phase_id:  # Attach phase name
      phase = phases_by_id.get(fv.phase_id)
      if not phase:
        logging.warning('Phase %d for field %s does not exist',
                        fv.phase_id, fd.field_name)
      else:
        new_fv.phaseName = phase.name
    field_values_list.append(new_fv)
  approval_values_list = convert_approvals(
      mar.cnxn, issue.approval_values, services, config, issue.phases)
  phases_list = convert_phases(issue.phases)
  with work_env.WorkEnv(mar, services) as we:
    starred = we.IsIssueStarred(issue)
  resp = cls(
      kind='monorail#issue',
      id=issue.local_id,
      title=issue.summary,
      summary=issue.summary,
      projectId=issue_project.project_name,
      stars=issue.star_count,
      starred=starred,
      status=issue.status,
      state=(api_pb2_v1.IssueState.open if
             tracker_helpers.MeansOpenInProject(
                 tracker_bizobj.GetStatus(issue), config)
             else api_pb2_v1.IssueState.closed),
      labels=issue.labels,
      components=component_list,
      author=convert_person(issue.reporter_id, mar.cnxn, services),
      owner=convert_person(issue.owner_id, mar.cnxn, services),
      cc=cc_list,
      updated=datetime.datetime.fromtimestamp(issue.modified_timestamp),
      published=datetime.datetime.fromtimestamp(issue.opened_timestamp),
      blockedOn=convert_issue_ids(issue.blocked_on_iids, mar, services),
      blocking=convert_issue_ids(issue.blocking_iids, mar, services),
      canComment=permissions.CanCommentIssue(
          mar.auth.effective_ids, mar.perms, issue_project, issue,
          granted_perms=granted_perms),
      canEdit=permissions.CanEditIssue(
          mar.auth.effective_ids, mar.perms, issue_project, issue,
          granted_perms=granted_perms),
      fieldValues=field_values_list,
      approvalValues=approval_values_list,
      phases=phases_list
  )
  if issue.closed_timestamp > 0:
    resp.closed = datetime.datetime.fromtimestamp(issue.closed_timestamp)
  if issue.merged_into:
    resp.mergedInto=convert_issue_ids([issue.merged_into], mar, services)[0]
  if issue.owner_modified_timestamp:
    resp.owner_modified = datetime.datetime.fromtimestamp(
        issue.owner_modified_timestamp)
  if issue.status_modified_timestamp:
    resp.status_modified = datetime.datetime.fromtimestamp(
        issue.status_modified_timestamp)
  if issue.component_modified_timestamp:
    resp.component_modified = datetime.datetime.fromtimestamp(
        issue.component_modified_timestamp)
  if migrated_id is not None:
    resp.migrated_id = migrated_id
  return resp


def convert_comment(issue, comment, mar, services, granted_perms):
  """Convert Monorail IssueComment PB to API IssueCommentWrapper."""

  perms = permissions.UpdateIssuePermissions(
      mar.perms, mar.project, issue, mar.auth.effective_ids,
      granted_perms=granted_perms)
  commenter = services.user.GetUser(mar.cnxn, comment.user_id)
  can_delete = permissions.CanDeleteComment(
      comment, commenter, mar.auth.user_id, perms)

  return api_pb2_v1.IssueCommentWrapper(
      attachments=[convert_attachment(a) for a in comment.attachments],
      author=convert_person(comment.user_id, mar.cnxn, services,
                            trap_exception=True),
      canDelete=can_delete,
      content=comment.content,
      deletedBy=convert_person(comment.deleted_by, mar.cnxn, services,
                               trap_exception=True),
      id=comment.sequence,
      published=datetime.datetime.fromtimestamp(comment.timestamp),
      updates=convert_amendments(issue, comment.amendments, mar, services),
      kind='monorail#issueComment',
      is_description=comment.is_description)

def convert_approval_comment(issue, comment, mar, services, granted_perms):
  perms = permissions.UpdateIssuePermissions(
      mar.perms, mar.project, issue, mar.auth.effective_ids,
      granted_perms=granted_perms)
  commenter = services.user.GetUser(mar.cnxn, comment.user_id)
  can_delete = permissions.CanDeleteComment(
      comment, commenter, mar.auth.user_id, perms)

  return api_pb2_v1.ApprovalCommentWrapper(
      attachments=[convert_attachment(a) for a in comment.attachments],
      author=convert_person(
          comment.user_id, mar.cnxn, services, trap_exception=True),
      canDelete=can_delete,
      content=comment.content,
      deletedBy=convert_person(comment.deleted_by, mar.cnxn, services,
                               trap_exception=True),
      id=comment.sequence,
      published=datetime.datetime.fromtimestamp(comment.timestamp),
      approvalUpdates=convert_approval_amendments(
          comment.amendments, mar, services),
      kind='monorail#approvalComment',
      is_description=comment.is_description)


def convert_attachment(attachment):
  """Convert Monorail Attachment PB to API Attachment."""

  return api_pb2_v1.Attachment(
      attachmentId=attachment.attachment_id,
      fileName=attachment.filename,
      fileSize=attachment.filesize,
      mimetype=attachment.mimetype,
      isDeleted=attachment.deleted)


def convert_amendments(issue, amendments, mar, services):
  """Convert a list of Monorail Amendment PBs to API Update."""
  amendments_user_ids = tracker_bizobj.UsersInvolvedInAmendments(amendments)
  users_by_id = framework_views.MakeAllUserViews(
      mar.cnxn, services.user, amendments_user_ids)
  framework_views.RevealAllEmailsToMembers(
      mar.cnxn, services, mar.auth, users_by_id, mar.project)

  result = api_pb2_v1.Update(kind='monorail#issueCommentUpdate')
  for amendment in amendments:
    if amendment.field == tracker_pb2.FieldID.SUMMARY:
      result.summary = amendment.newvalue
    elif amendment.field == tracker_pb2.FieldID.STATUS:
      result.status = amendment.newvalue
    elif amendment.field == tracker_pb2.FieldID.OWNER:
      if len(amendment.added_user_ids) == 0:
        result.owner = framework_constants.NO_USER_NAME
      else:
        result.owner = _get_user_email(
            services.user, mar.cnxn, amendment.added_user_ids[0])
    elif amendment.field == tracker_pb2.FieldID.LABELS:
      result.labels = amendment.newvalue.split()
    elif amendment.field == tracker_pb2.FieldID.CC:
      for user_id in amendment.added_user_ids:
        user_email = _get_user_email(
            services.user, mar.cnxn, user_id)
        result.cc.append(user_email)
      for user_id in amendment.removed_user_ids:
        user_email = _get_user_email(
            services.user, mar.cnxn, user_id)
        result.cc.append('-%s' % user_email)
    elif amendment.field == tracker_pb2.FieldID.BLOCKEDON:
      result.blockedOn = _append_project(
          amendment.newvalue, issue.project_name)
    elif amendment.field == tracker_pb2.FieldID.BLOCKING:
      result.blocking = _append_project(
          amendment.newvalue, issue.project_name)
    elif amendment.field == tracker_pb2.FieldID.MERGEDINTO:
      result.mergedInto = amendment.newvalue
    elif amendment.field == tracker_pb2.FieldID.COMPONENTS:
      result.components = amendment.newvalue.split()
    elif amendment.field == tracker_pb2.FieldID.CUSTOM:
      fv = api_pb2_v1.FieldValue()
      fv.fieldName = amendment.custom_field_name
      fv.fieldValue = tracker_bizobj.AmendmentString(amendment, users_by_id)
      result.fieldValues.append(fv)

  return result


def convert_approval_amendments(amendments, mar, services):
  """Convert a list of Monorail Amendment PBs API ApprovalUpdate."""
  amendments_user_ids = tracker_bizobj.UsersInvolvedInAmendments(amendments)
  users_by_id = framework_views.MakeAllUserViews(
      mar.cnxn, services.user, amendments_user_ids)
  framework_views.RevealAllEmailsToMembers(
      mar.cnxn, services, mar.auth, users_by_id, mar.project)

  result = api_pb2_v1.ApprovalUpdate(kind='monorail#approvalCommentUpdate')
  for amendment in amendments:
    if amendment.field == tracker_pb2.FieldID.CUSTOM:
      if amendment.custom_field_name == 'Status':
        status_number = tracker_pb2.ApprovalStatus(
            amendment.newvalue.upper()).number
        result.status = api_pb2_v1.ApprovalStatus(status_number).name
      elif amendment.custom_field_name == 'Approvers':
        for user_id in amendment.added_user_ids:
          user_email = _get_user_email(
              services.user, mar.cnxn, user_id)
          result.approvers.append(user_email)
        for user_id in amendment.removed_user_ids:
          user_email = _get_user_email(
              services.user, mar.cnxn, user_id)
          result.approvers.append('-%s' % user_email)
      else:
        fv = api_pb2_v1.FieldValue()
        fv.fieldName = amendment.custom_field_name
        fv.fieldValue = tracker_bizobj.AmendmentString(amendment, users_by_id)
        # TODO(jojwang): monorail:4229, add approvalName field to FieldValue
        result.fieldValues.append(fv)

  return result


def _get_user_email(user_service, cnxn, user_id):
  """Get user email."""

  if user_id == framework_constants.DELETED_USER_ID:
    return framework_constants.DELETED_USER_NAME
  if not user_id:
    # _get_user_email should handle getting emails for optional user values,
    # like issue.owner where user_id may be None.
    return framework_constants.NO_USER_NAME
  try:
    user_email = user_service.LookupUserEmail(
            cnxn, user_id)
  except exceptions.NoSuchUserException:
    user_email = framework_constants.USER_NOT_FOUND_NAME
  return user_email


def _append_project(issue_ids, project_name):
  """Append project name to convert <id> to <project>:<id> format."""

  result = []
  id_list = issue_ids.split()
  for id_str in id_list:
    if ':' in id_str:
      result.append(id_str)
    # '-' means this issue is being removed
    elif id_str.startswith('-'):
      result.append('-%s:%s' % (project_name, id_str[1:]))
    else:
      result.append('%s:%s' % (project_name, id_str))
  return result


def split_remove_add(item_list):
  """Split one list of items into two: items to add and items to remove."""

  list_to_add = []
  list_to_remove = []

  for item in item_list:
    if item.startswith('-'):
      list_to_remove.append(item[1:])
    else:
      list_to_add.append(item)

  return list_to_add, list_to_remove


# TODO(sheyang): batch the SQL queries to fetch projects/issues.
def issue_global_ids(project_local_id_pairs, project_id, mar, services):
  """Find global issues ids given <project_name>:<issue_local_id> pairs."""

  result = []
  for pair in project_local_id_pairs:
    issue_project_id = None
    local_id = None
    if ':' in pair:
      pair_ary = pair.split(':')
      project_name = pair_ary[0]
      local_id = int(pair_ary[1])
      project = services.project.GetProjectByName(mar.cnxn, project_name)
      if not project:
        raise exceptions.NoSuchProjectException(
            'Project %s does not exist' % project_name)
      issue_project_id = project.project_id
    else:
      issue_project_id = project_id
      local_id = int(pair)
    result.append(
        services.issue.LookupIssueID(mar.cnxn, issue_project_id, local_id))

  return result


def convert_group_settings(group_name, setting):
  """Convert UserGroupSettings to UserGroupSettingsWrapper."""
  return api_pb2_v1.UserGroupSettingsWrapper(
      groupName=group_name,
      who_can_view_members=setting.who_can_view_members,
      ext_group_type=setting.ext_group_type,
      last_sync_time=setting.last_sync_time)


def convert_component_def(cd, mar, services):
  """Convert ComponentDef PB to Component PB."""
  project_name = services.project.LookupProjectNames(
      mar.cnxn, [cd.project_id])[cd.project_id]
  user_ids = set()
  user_ids.update(
      cd.admin_ids + cd.cc_ids + [cd.creator_id] + [cd.modifier_id])
  user_names_dict = services.user.LookupUserEmails(mar.cnxn, list(user_ids))
  component = api_pb2_v1.Component(
      componentId=cd.component_id,
      projectName=project_name,
      componentPath=cd.path,
      description=cd.docstring,
      admin=sorted([user_names_dict[uid] for uid in cd.admin_ids]),
      cc=sorted([user_names_dict[uid] for uid in cd.cc_ids]),
      deprecated=cd.deprecated)
  if cd.created:
    component.created = datetime.datetime.fromtimestamp(cd.created)
    component.creator = user_names_dict[cd.creator_id]
  if cd.modified:
    component.modified = datetime.datetime.fromtimestamp(cd.modified)
    component.modifier = user_names_dict[cd.modifier_id]
  return component


def convert_component_ids(config, component_names):
  """Convert a list of component names to ids."""
  component_names_lower = [name.lower() for name in component_names]
  result = []
  for cd in config.component_defs:
    cpath = cd.path
    if cpath.lower() in component_names_lower:
      result.append(cd.component_id)
  return result


def convert_field_values(field_values, mar, services):
  """Convert user passed in field value list to FieldValue PB, or labels."""
  fv_list_add = []
  fv_list_remove = []
  fv_list_clear = []
  label_list_add = []
  label_list_remove = []
  field_name_dict = {
      fd.field_name: fd for fd in mar.config.field_defs}

  for fv in field_values:
    field_def = field_name_dict.get(fv.fieldName)
    if not field_def:
      logging.warning('Custom field %s of does not exist', fv.fieldName)
      continue

    if fv.operator == api_pb2_v1.FieldValueOperator.clear:
      fv_list_clear.append(field_def.field_id)
      continue

    # Enum fields are stored as labels
    if field_def.field_type == tracker_pb2.FieldTypes.ENUM_TYPE:
      raw_val = '%s-%s' % (fv.fieldName, fv.fieldValue)
      if fv.operator == api_pb2_v1.FieldValueOperator.remove:
        label_list_remove.append(raw_val)
      elif fv.operator == api_pb2_v1.FieldValueOperator.add:
        label_list_add.append(raw_val)
      else:  # pragma: no cover
        logging.warning('Unsupported field value operater %s', fv.operator)
    else:
      new_fv = field_helpers.ParseOneFieldValue(
          mar.cnxn, services.user, field_def, fv.fieldValue)
      if fv.operator == api_pb2_v1.FieldValueOperator.remove:
        fv_list_remove.append(new_fv)
      elif fv.operator == api_pb2_v1.FieldValueOperator.add:
        fv_list_add.append(new_fv)
      else:  # pragma: no cover
        logging.warning('Unsupported field value operater %s', fv.operator)

  return (fv_list_add, fv_list_remove, fv_list_clear,
          label_list_add, label_list_remove)
