# Copyright 2017 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

"""Helper functions for deciding who to notify and why.."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import logging

import settings
from features import filterrules_helpers
from features import savedqueries_helpers
from framework import authdata
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 proto import tracker_pb2
from search import query2ast
from search import searchpipeline
from tracker import component_helpers
from tracker import tracker_bizobj

# When sending change notification emails, choose the reply-to header and
# footer message based on three levels of the recipient's permissions
# for that issue.
REPLY_NOT_ALLOWED = 'REPLY_NOT_ALLOWED'
REPLY_MAY_COMMENT = 'REPLY_MAY_COMMENT'
REPLY_MAY_UPDATE = 'REPLY_MAY_UPDATE'

# These are strings describing the various reasons that we send notifications.
REASON_REPORTER = 'You reported this issue'
REASON_OWNER = 'You are the owner of the issue'
REASON_OLD_OWNER = 'You were the issue owner before this change'
REASON_DEFAULT_OWNER = 'A rule made you owner of the issue'
REASON_CCD = 'You were specifically CC\'d on the issue'
REASON_DEFAULT_CCD = 'A rule CC\'d you on the issue'
# TODO(crbug.com/monorail/2857): separate reasons for notification to group
# members resulting from component and rules derived ccs.
REASON_GROUP_CCD = (
    'A group you\'re a member of was specifically CC\'d on the issue')
REASON_STARRER = 'You starred the issue'
REASON_SUBSCRIBER = 'Your saved query matched the issue'
REASON_ALSO_NOTIFY = 'A rule was set up to notify you'
REASON_ALL_NOTIFICATIONS = (
    'The project was configured to send all issue notifications '
    'to this address')
REASON_LINKED_ACCOUNT = 'Your linked account would have been notified'

# An AddrPerm is how we represent our decision to notify a given
# email address, which version of the email body to send to them, and
# whether to offer them the option to reply to the notification.  Many
# of the functions in this file pass around AddrPerm lists (an "APL").
# is_member is a boolean
# address is a string email address
# user is a User PB, including built-in user preference fields.
# reply_perm is one of REPLY_NOT_ALLOWED, REPLY_MAY_COMMENT,
# REPLY_MAY_UPDATE.
# user_prefs is a UserPrefs object with string->string user prefs.
AddrPerm = collections.namedtuple(
    'AddrPerm', 'is_member, address, user, reply_perm, user_prefs')



def ComputeIssueChangeAddressPermList(
    cnxn, ids_to_consider, project, issue, services, omit_addrs,
    users_by_id, pref_check_function=lambda u: u.notify_issue_change):
  """Return a list of user email addresses to notify of an issue change.

  User email addresses are determined by looking up the given user IDs
  in the given users_by_id dict.

  Args:
    cnxn: connection to SQL database.
    ids_to_consider: list of user IDs for users interested in this issue.
    project: Project PB for the project containing this issue.
    issue: Issue PB for the issue that was updated.
    services: Services.
    omit_addrs: set of strings for email addresses to not notify because
        they already know.
    users_by_id: dict {user_id: user_view} user info.
    pref_check_function: optional function to use to check if a certain
        User PB has a preference set to receive the email being sent.  It
        defaults to "If I am in the issue's owner or cc field", but it
        can be set to check "If I starred the issue."

  Returns:
    A list of AddrPerm objects.
  """
  memb_addr_perm_list = []
  logging.info('Considering %r ', ids_to_consider)
  all_user_prefs = services.user.GetUsersPrefs(cnxn, ids_to_consider)
  for user_id in ids_to_consider:
    if user_id == framework_constants.NO_USER_SPECIFIED:
      continue
    user = services.user.GetUser(cnxn, user_id)
    # Notify people who have a pref set, or if they have no User PB
    # because the pref defaults to True.
    if user and not pref_check_function(user):
      logging.info('Not notifying %r: user preference', user.email)
      continue
    # TODO(jrobbins): doing a bulk operation would reduce DB load.
    auth = authdata.AuthData.FromUserID(cnxn, user_id, services)
    perms = permissions.GetPermissions(user, auth.effective_ids, project)
    config = services.config.GetProjectConfig(cnxn, project.project_id)
    granted_perms = tracker_bizobj.GetGrantedPerms(
        issue, auth.effective_ids, config)

    if not permissions.CanViewIssue(
        auth.effective_ids, perms, project, issue,
        granted_perms=granted_perms):
      logging.info('Not notifying %r: user cannot view issue', user.email)
      continue

    addr = users_by_id[user_id].email
    if addr in omit_addrs:
      logging.info('Not notifying %r: user already knows', user.email)
      continue

    recipient_is_member = bool(framework_bizobj.UserIsInProject(
        project, auth.effective_ids))

    reply_perm = REPLY_NOT_ALLOWED
    if project.process_inbound_email:
      if permissions.CanEditIssue(auth.effective_ids, perms, project, issue):
        reply_perm = REPLY_MAY_UPDATE
      elif permissions.CanCommentIssue(
          auth.effective_ids, perms, project, issue):
        reply_perm = REPLY_MAY_COMMENT

    memb_addr_perm_list.append(
      AddrPerm(recipient_is_member, addr, user, reply_perm,
               all_user_prefs[user_id]))

  logging.info('For %s %s, will notify: %r',
               project.project_name, issue.local_id,
               [ap.address for ap in memb_addr_perm_list])

  return memb_addr_perm_list


def ComputeProjectNotificationAddrList(
    cnxn, services, project, contributor_could_view, omit_addrs):
  """Return a list of non-user addresses to notify of an issue change.

  The non-user addresses are specified by email address strings, not
  user IDs.  One such address can be specified in the project PB.
  It is not assumed to have permission to see all issues.

  Args:
    cnxn: connection to SQL database.
    services: A Services object.
    project: Project PB containing the issue that was updated.
    contributor_could_view: True if any project contributor should be able to
        see the notification email, e.g., in a mailing list archive or feed.
    omit_addrs: set of strings for email addresses to not notify because
        they already know.

  Returns:
    A list of tuples: [(False, email_addr, None, reply_permission_level), ...],
    where reply_permission_level is always REPLY_NOT_ALLOWED for now.
  """
  memb_addr_perm_list = []
  if contributor_could_view:
    ml_addr = project.issue_notify_address
    ml_user_prefs = services.user.GetUserPrefsByEmail(cnxn, ml_addr)

    if ml_addr and ml_addr not in omit_addrs:
      memb_addr_perm_list.append(
          AddrPerm(False, ml_addr, None, REPLY_NOT_ALLOWED, ml_user_prefs))

  return memb_addr_perm_list


def ComputeIssueNotificationAddrList(cnxn, services, issue, omit_addrs):
  """Return a list of non-user addresses to notify of an issue change.

  The non-user addresses are specified by email address strings, not
  user IDs.  They can be set by filter rules with the "Also notify" action.
  "Also notify" addresses are assumed to have permission to see any issue,
  even a restricted one.

  Args:
    cnxn: connection to SQL database.
    services: A Services object.
    issue: Issue PB for the issue that was updated.
    omit_addrs: set of strings for email addresses to not notify because
        they already know.

  Returns:
    A list of tuples: [(False, email_addr, None, reply_permission_level), ...],
    where reply_permission_level is always REPLY_NOT_ALLOWED for now.
  """
  addr_perm_list = []
  for addr in issue.derived_notify_addrs:
    if addr not in omit_addrs:
      notify_user_prefs = services.user.GetUserPrefsByEmail(cnxn, addr)
      addr_perm_list.append(
          AddrPerm(False, addr, None, REPLY_NOT_ALLOWED, notify_user_prefs))

  return addr_perm_list


def _GetSubscribersAddrPermList(
    cnxn, services, issue, project, config, omit_addrs, users_by_id):
  """Lookup subscribers, evaluate their saved queries, and decide to notify."""
  users_to_queries = GetNonOmittedSubscriptions(
      cnxn, services, [project.project_id], omit_addrs)
  # TODO(jrobbins): need to pass through the user_id to use for "me".
  subscribers_to_notify = EvaluateSubscriptions(
      cnxn, issue, users_to_queries, services, config)
  # TODO(jrobbins): expand any subscribers that are user groups.
  subs_needing_user_views = [
      uid for uid in subscribers_to_notify if uid not in users_by_id]
  users_by_id.update(framework_views.MakeAllUserViews(
      cnxn, services.user, subs_needing_user_views))
  sub_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, subscribers_to_notify, project, issue, services, omit_addrs,
      users_by_id, pref_check_function=lambda *args: True)

  return sub_addr_perm_list


def EvaluateSubscriptions(
    cnxn, issue, users_to_queries, services, config):
  """Determine subscribers who have subs that match the given issue."""
  # Note: unlike filter rule, subscriptions see explicit & derived values.
  lower_labels = [lab.lower() for lab in tracker_bizobj.GetLabels(issue)]
  label_set = set(lower_labels)

  subscribers_to_notify = []
  for uid, saved_queries in users_to_queries.items():
    for sq in saved_queries:
      if sq.subscription_mode != 'immediate':
        continue
      if issue.project_id not in sq.executes_in_project_ids:
        continue
      cond = savedqueries_helpers.SavedQueryToCond(sq)
      # TODO(jrobbins): Support linked accounts me_user_ids.
      cond, _warnings = searchpipeline.ReplaceKeywordsWithUserIDs([uid], cond)
      cond_ast = query2ast.ParseUserQuery(
        cond, '', query2ast.BUILTIN_ISSUE_FIELDS, config)

      if filterrules_helpers.EvalPredicate(
          cnxn, services, cond_ast, issue, label_set, config,
          tracker_bizobj.GetOwnerId(issue), tracker_bizobj.GetCcIds(issue),
          tracker_bizobj.GetStatus(issue)):
        subscribers_to_notify.append(uid)
        break  # Don't bother looking at the user's other saved quereies.

  return subscribers_to_notify


def GetNonOmittedSubscriptions(cnxn, services, project_ids, omit_addrs):
  """Get a dict of users w/ subscriptions in those projects."""
  users_to_queries = services.features.GetSubscriptionsInProjects(
      cnxn, project_ids)
  user_emails = services.user.LookupUserEmails(
      cnxn, list(users_to_queries.keys()))
  for user_id, email in user_emails.items():
    if email in omit_addrs:
      del users_to_queries[user_id]
  return users_to_queries


def ComputeCustomFieldAddrPerms(
    cnxn, config, issue, project, services, omit_addrs, users_by_id):
  """Check the reasons to notify users named in custom fields."""
  group_reason_list = []
  for fd in config.field_defs:
    (direct_named_ids,
     transitive_named_ids) = services.usergroup.ExpandAnyGroupEmailRecipients(
         cnxn, ComputeNamedUserIDsToNotify(issue.field_values, fd))
    named_user_ids = direct_named_ids + transitive_named_ids
    if named_user_ids:
      named_addr_perms = ComputeIssueChangeAddressPermList(
          cnxn, named_user_ids, project, issue, services, omit_addrs,
          users_by_id, pref_check_function=lambda u: True)
      group_reason_list.append(
          (named_addr_perms, 'You are named in the %s field' % fd.field_name))

  return group_reason_list


def ComputeNamedUserIDsToNotify(field_values, fd):
  """Give a list of user IDs to notify because they're in a field."""
  if (fd.field_type == tracker_pb2.FieldTypes.USER_TYPE and
      fd.notify_on == tracker_pb2.NotifyTriggers.ANY_COMMENT):
    return [fv.user_id for fv in field_values
            if fv.field_id == fd.field_id]

  return []


def ComputeComponentFieldAddrPerms(
    cnxn, config, issue, project, services, omit_addrs, users_by_id):
  """Return [(addr_perm_list, reason),...] for users auto-cc'd by components."""
  component_ids = set(issue.component_ids)
  group_reason_list = []
  for cd in config.component_defs:
    if cd.component_id in component_ids:
      (direct_ccs,
       transitive_ccs) = services.usergroup.ExpandAnyGroupEmailRecipients(
           cnxn, component_helpers.GetCcIDsForComponentAndAncestors(config, cd))
      cc_ids = direct_ccs + transitive_ccs
      comp_addr_perms = ComputeIssueChangeAddressPermList(
          cnxn, cc_ids, project, issue, services, omit_addrs,
          users_by_id, pref_check_function=lambda u: True)
      group_reason_list.append(
          (comp_addr_perms,
           'You are auto-CC\'d on all issues in component %s' % cd.path))

  return group_reason_list


def ComputeGroupReasonList(
    cnxn, services, project, issue, config, users_by_id, omit_addrs,
    contributor_could_view, starrer_ids=None, noisy=False,
    old_owner_id=None, commenter_in_project=True, include_subscribers=True,
    include_notify_all=True,
    starrer_pref_check_function=lambda u: u.notify_starred_issue_change):
  """Return a list [(addr_perm_list, reason),...] of addrs to notify."""
  # Get the transitive set of owners and Cc'd users, and their UserViews.
  starrer_ids = starrer_ids or []
  reporter = [issue.reporter_id] if issue.reporter_id in starrer_ids else []
  if old_owner_id:
    old_direct_owners, old_transitive_owners = (
        services.usergroup.ExpandAnyGroupEmailRecipients(cnxn, [old_owner_id]))
  else:
    old_direct_owners, old_transitive_owners = [], []

  direct_owners, transitive_owners = (
      services.usergroup.ExpandAnyGroupEmailRecipients(cnxn, [issue.owner_id]))
  der_direct_owners, der_transitive_owners = (
      services.usergroup.ExpandAnyGroupEmailRecipients(
          cnxn, [issue.derived_owner_id]))
  direct_comp, trans_comp = services.usergroup.ExpandAnyGroupEmailRecipients(
      cnxn, component_helpers.GetComponentCcIDs(issue, config))
  direct_ccs, transitive_ccs = services.usergroup.ExpandAnyGroupEmailRecipients(
      cnxn, list(issue.cc_ids))
  der_direct_ccs, der_transitive_ccs = (
      services.usergroup.ExpandAnyGroupEmailRecipients(
          cnxn, list(issue.derived_cc_ids)))
  # Remove cc's derived from components, which are grouped into their own
  # notify-reason-group in ComputeComponentFieldAddrPerms().
  # This means that an exact email cc'd by both a component and a rule will
  # get an email that says they are only being notified because of the
  # component.
  # Note that a user directly cc'd due to a rule who is also part of a
  # group cc'd due to a component, will get a message saying they're cc'd for
  # both the rule and the component.
  der_direct_ccs = list(set(der_direct_ccs).difference(set(direct_comp)))
  der_transitive_ccs = list(set(der_transitive_ccs).difference(set(trans_comp)))

  users_by_id.update(framework_views.MakeAllUserViews(
      cnxn, services.user, transitive_owners, der_transitive_owners,
      direct_comp, trans_comp, transitive_ccs, der_transitive_ccs))

  # Notify interested people according to the reason for their interest:
  # owners, component auto-cc'd users, cc'd users, starrers, and
  # other notification addresses.
  reporter_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, reporter, project, issue, services, omit_addrs, users_by_id)
  owner_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, direct_owners + transitive_owners, project, issue,
      services, omit_addrs, users_by_id)
  old_owner_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, old_direct_owners + old_transitive_owners, project, issue,
      services, omit_addrs, users_by_id)
  owner_addr_perm_set = set(owner_addr_perm_list)
  old_owner_addr_perm_list = [ap for ap in old_owner_addr_perm_list
                              if ap not in owner_addr_perm_set]
  der_owner_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, der_direct_owners + der_transitive_owners, project, issue,
      services, omit_addrs, users_by_id)
  cc_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, direct_ccs, project, issue, services, omit_addrs, users_by_id)
  transitive_cc_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, transitive_ccs, project, issue, services, omit_addrs, users_by_id)
  der_cc_addr_perm_list = ComputeIssueChangeAddressPermList(
      cnxn, der_direct_ccs + der_transitive_ccs, project, issue,
      services, omit_addrs, users_by_id)

  starrer_addr_perm_list = []
  sub_addr_perm_list = []
  if not noisy or commenter_in_project:
    # Avoid an OOM by only notifying a number of starrers that we can handle.
    # And, we really should limit the number of emails that we send anyway.
    max_starrers = settings.max_starrers_to_notify
    starrer_ids = starrer_ids[-max_starrers:]
    # Note: starrers can never be user groups.
    starrer_addr_perm_list = (
        ComputeIssueChangeAddressPermList(
            cnxn, starrer_ids, project, issue,
            services, omit_addrs, users_by_id,
            pref_check_function=starrer_pref_check_function))

    if include_subscribers:
      sub_addr_perm_list = _GetSubscribersAddrPermList(
          cnxn, services, issue, project, config, omit_addrs,
          users_by_id)

  # Get the list of addresses to notify based on filter rules.
  issue_notify_addr_list = ComputeIssueNotificationAddrList(
      cnxn, services, issue, omit_addrs)
  # Get the list of addresses to notify based on project settings.
  proj_notify_addr_list = []
  if include_notify_all:
    proj_notify_addr_list = ComputeProjectNotificationAddrList(
        cnxn, services, project, contributor_could_view, omit_addrs)

  group_reason_list = [
      (reporter_addr_perm_list, REASON_REPORTER),
      (owner_addr_perm_list, REASON_OWNER),
      (old_owner_addr_perm_list, REASON_OLD_OWNER),
      (der_owner_addr_perm_list, REASON_DEFAULT_OWNER),
      (cc_addr_perm_list, REASON_CCD),
      (transitive_cc_addr_perm_list, REASON_GROUP_CCD),
      (der_cc_addr_perm_list, REASON_DEFAULT_CCD),
  ]
  group_reason_list.extend(ComputeComponentFieldAddrPerms(
      cnxn, config, issue, project, services, omit_addrs,
      users_by_id))
  group_reason_list.extend(ComputeCustomFieldAddrPerms(
      cnxn, config, issue, project, services, omit_addrs,
      users_by_id))
  group_reason_list.extend([
      (starrer_addr_perm_list, REASON_STARRER),
      (sub_addr_perm_list, REASON_SUBSCRIBER),
      (issue_notify_addr_list, REASON_ALSO_NOTIFY),
      (proj_notify_addr_list, REASON_ALL_NOTIFICATIONS),
      ])
  return group_reason_list
