# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is govered 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 email notifications of issue changes."""

import cgi
import logging
import re

from django.utils.html import urlize

from features import filterrules_helpers
from features import savedqueries_helpers
from framework import emailfmt
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import monorailrequest
from framework import permissions
from framework import urls
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 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'

# This HTML template adds mark up which enables Gmail/Inbox to display a
# convenient link that takes users to the CL directly from the inbox without
# having to click on the email.
# Documentation for this schema.org markup is here:
#   https://developers.google.com/gmail/markup/reference/go-to-action
HTML_BODY_WITH_GMAIL_ACTION_TEMPLATE = """
<html>
<body>
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "EmailMessage",
  "potentialAction": {
    "@type": "ViewAction",
    "name": "View Issue",
    "url": "%s"
  },
  "description": ""
}
</script>

<div style="font-family: arial, sans-serif">%s</div>
</body>
</html>
"""


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 contianing 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 tuples: [(recipient_is_member, address, reply_perm), ...] where
    reply_perm is one of REPLY_NOT_ALLOWED, REPLY_MAY_COMMENT,
    REPLY_MAY_UPDATE.
  """
  memb_addr_perm_list = []
  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):
      continue
    # TODO(jrobbins): doing a bulk operation would reduce DB load.
    auth = monorailrequest.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):
      continue

    addr = users_by_id[user_id].email
    if addr in omit_addrs:
      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((recipient_is_member, addr, reply_perm))

  logging.info('For %s %s, will notify: %r',
               project.project_name, issue.local_id, memb_addr_perm_list)

  return memb_addr_perm_list


def ComputeProjectNotificationAddrList(
    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:
    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_address, 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
    if ml_addr and ml_addr not in omit_addrs:
      memb_addr_perm_list.append((False, ml_addr, REPLY_NOT_ALLOWED))

  return memb_addr_perm_list


def ComputeIssueNotificationAddrList(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:
    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_address, 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:
      addr_perm_list.append((False, addr, REPLY_NOT_ALLOWED))

  return addr_perm_list


def MakeBulletedEmailWorkItems(
    group_reason_list, subject, body_for_non_members, body_for_members,
    project, hostport, commenter_view, seq_num=None, detail_url=None):
  """Make a list of dicts describing email-sending tasks to notify users.

  Args:
    group_reason_list: list of (is_memb, addr_perm, reason) tuples.
    subject: string email subject line.
    body_for_non_members: string body of email to send to non-members.
    body_for_members: string body of email to send to members.
    project: Project that contains the issue.
    hostport: string hostname and port number for links to the site.
    commenter_view: UserView for the user who made the comment.
    seq_num: optional int sequence number of the comment.
    detail_url: optional str direct link to the issue.

  Returns:
    A list of dictionaries, each with all needed info to send an individual
    email to one user.  Each email contains a footer that lists all the
    reasons why that user received the email.
  """
  logging.info('group_reason_list is %r', group_reason_list)
  addr_reasons_dict = {}
  for group, reason in group_reason_list:
    for memb_addr_perm in group:
      addr_reasons_dict.setdefault(memb_addr_perm, []).append(reason)

  email_tasks = []
  for memb_addr_perm, reasons in addr_reasons_dict.iteritems():
    email_tasks.append(_MakeEmailWorkItem(
        memb_addr_perm, reasons, subject, body_for_non_members,
        body_for_members, project, hostport, commenter_view, seq_num=seq_num,
        detail_url=detail_url))

  return email_tasks


def _MakeEmailWorkItem(
    (recipient_is_member, to_addr, reply_perm), reasons, subject,
    body_for_non_members, body_for_members, project, hostport, commenter_view,
    seq_num=None, detail_url=None):
  """Make one email task dict for one user, includes a detailed reason."""
  footer = _MakeNotificationFooter(reasons, reply_perm, hostport)
  if isinstance(footer, unicode):
    footer = footer.encode('utf-8')
  if recipient_is_member:
    logging.info('got member %r', to_addr)
    body = body_for_members
  else:
    logging.info('got non-member %r', to_addr)
    body = body_for_non_members

  logging.info('sending body + footer: %r', body + footer)
  can_reply_to = (
      reply_perm != REPLY_NOT_ALLOWED and project.process_inbound_email)
  from_addr = emailfmt.FormatFromAddr(
    project, commenter_view=commenter_view, reveal_addr=recipient_is_member,
    can_reply_to=can_reply_to)
  if can_reply_to:
    reply_to = '%s@%s' % (project.project_name, emailfmt.MailDomain())
  else:
    reply_to = emailfmt.NoReplyAddress()
  refs = emailfmt.GetReferences(
    to_addr, subject, seq_num,
    '%s@%s' % (project.project_name, emailfmt.MailDomain()))
  # If detail_url is specified then we can use markup to display a convenient
  # link that takes users directly to the issue without clicking on the email.
  html_body = None
  if detail_url:
    # cgi.escape the body and additionally escape single quotes which are
    # occassionally used to contain HTML attributes and event handler
    # definitions.
    html_escaped_body = cgi.escape(body + footer, quote=1).replace("'", '&#39;')
    html_body = HTML_BODY_WITH_GMAIL_ACTION_TEMPLATE % (
        detail_url,
        _AddHTMLTags(html_escaped_body.decode('utf-8')))
  return dict(to=to_addr, subject=subject, body=body + footer,
              html_body=html_body, from_addr=from_addr, reply_to=reply_to,
              references=refs)


def _AddHTMLTags(body):
  """Adds HMTL tags in the specified email body.

  Specifically does the following:
  * Detects links and adds <a href>s around the links.
  * Substitutes <br/> for all occurrences of "\n".

  See crbug.com/582463 for context.
  """
  # Convert all URLs into clickable links.
  body = urlize(body)
  # The above step converts
  #   '&lt;link.com&gt;' into '&lt;<a href="link.com&gt">link.com&gt</a>;' and
  #   '&lt;x@y.com&gt;' into '&lt;<a href="mailto:x@y.com&gt">x@y.com&gt</a>;'
  # The below regex fixes this specific problem. See
  # https://bugs.chromium.org/p/monorail/issues/detail?id=1007 for more details.
  body = re.sub(r'&lt;<a href="(|mailto:)(.*?)&gt">(.*?)&gt</a>;',
                r'<a href="\1\2"><\3></a>', body)

  # Convert all "\n"s into "<br/>"s.
  body = body.replace("\n", "<br/>")
  return body


def _MakeNotificationFooter(reasons, reply_perm, hostport):
  """Make an informative footer for a notification email.

  Args:
    reasons: a list of strings to be used as the explanation.  Empty if no
        reason is to be given.
    reply_perm: string which is one of REPLY_NOT_ALLOWED, REPLY_MAY_COMMENT,
        REPLY_MAY_UPDATE.
    hostport: string with domain_name:port_number to be used in linking to
        the user preferences page.

  Returns:
    A string to be used as the email footer.
  """
  if not reasons:
    return ''

  domain_port = hostport.split(':')
  domain_port[0] = framework_helpers.GetPreferredDomain(domain_port[0])
  hostport = ':'.join(domain_port)

  prefs_url = 'https://%s%s' % (hostport, urls.USER_SETTINGS)
  lines = ['-- ']
  lines.append('You received this message because:')
  lines.extend('  %d. %s' % (idx + 1, reason)
               for idx, reason in enumerate(reasons))

  lines.extend(['', 'You may adjust your notification preferences at:',
                prefs_url])

  if reply_perm == REPLY_MAY_COMMENT:
    lines.extend(['', 'Reply to this email to add a comment.'])
  elif reply_perm == REPLY_MAY_UPDATE:
    lines.extend(['', 'Reply to this email to add a comment or make updates.'])

  return '\n'.join(lines)


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, users_to_queries.keys())
  for user_id, email in user_emails.iteritems():
    if email in omit_addrs:
      del users_to_queries[user_id]

  return users_to_queries


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.iteritems():
    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)
      logging.info('evaluating query %s: %r', sq.name, cond)
      cond = searchpipeline.ReplaceKeywordsWithUserID(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 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:
    named_user_ids = ComputeNamedUserIDsToNotify(issue, fd)
    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(issue, 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 issue.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, 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:
      cc_ids = component_helpers.GetCcIDsForComponentAndAncestors(config, cd)
      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
