# 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.

"""Helper functions for email notifications of issue changes."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import json
import logging

import ezt
import six

from features import autolink
from features import autolink_constants
from features import features_constants
from features import filterrules_helpers
from features import savedqueries_helpers
from features import notify_reasons
from framework import cloud_tasks_helpers
from framework import emailfmt
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import jsonfeed
from framework import monorailrequest
from framework import permissions
from framework import template_helpers
from framework import urls
from mrproto import tracker_pb2
from search import query2ast
from search import searchpipeline
from tracker import tracker_bizobj


# Email tasks can get too large for AppEngine to handle. In order to prevent
# that, we set a maximum body size, and may truncate messages to that length.
# We set this value to 35k so that the total of 35k body + 35k html_body +
# metadata does not exceed AppEngine's limit of 100k.
MAX_EMAIL_BODY_SIZE = 35 * 1024

# 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": "%(url)s"
  },
  "description": ""
}
</script>

<div style="font-family: arial, sans-serif; white-space:pre">%(body)s</div>
</body>
</html>
"""

HTML_BODY_WITHOUT_GMAIL_ACTION_TEMPLATE = """
<html>
<body>
<div style="font-family: arial, sans-serif; white-space:pre">%(body)s</div>
</body>
</html>
"""


NOTIFY_RESTRICTED_ISSUES_PREF_NAME = 'notify_restricted_issues'
NOTIFY_WITH_DETAILS = 'notify with details'
NOTIFY_WITH_DETAILS_GOOGLE = 'notify with details: Google'
NOTIFY_WITH_LINK_ONLY = 'notify with link only'


def _EnqueueOutboundEmail(message_dict):
  """Create a task to send one email message, all fields are in the dict.

  We use a separate task for each outbound email to isolate errors.

  Args:
    message_dict: dict with all needed info for the task.
  """
  # We use a JSON-encoded payload because it ensures that the task size is
  # effectively the same as the sum of the email bodies. Using params results
  # in the dict being urlencoded, which can (worst case) triple the size of
  # an email body containing many characters which need to be escaped.
  payload = json.dumps(message_dict)
  task = {
      'app_engine_http_request':
          {
              'relative_uri': urls.OUTBOUND_EMAIL_TASK + '.do',
              # Cloud Tasks expects body to be in bytes.
              'body': payload.encode(),
              # Cloud tasks default body content type is octet-stream.
              'headers': {
                  'Content-type': 'application/json'
              }
          }
  }
  cloud_tasks_helpers.create_task(
      task, queue=features_constants.QUEUE_OUTBOUND_EMAIL)


def AddAllEmailTasks(tasks):
  """Add one GAE task for each email to be sent."""
  notified = []
  for task in tasks:
    _EnqueueOutboundEmail(task)
    notified.append(task['to'])

  return notified


class NotifyTaskBase(jsonfeed.InternalTask):
  """Abstract base class for notification task handler."""

  _EMAIL_TEMPLATE = None  # Subclasses must override this.
  _LINK_ONLY_EMAIL_TEMPLATE = None  # Subclasses may override this.

  CHECK_SECURITY_TOKEN = False

  def __init__(self, *args, **kwargs):
    super(NotifyTaskBase, self).__init__(*args, **kwargs)

    if not self._EMAIL_TEMPLATE:
      raise Exception('Subclasses must override _EMAIL_TEMPLATE.'
                      ' This class must not be called directly.')
    # We use FORMAT_RAW for emails because they are plain text, not HTML.
    # TODO(jrobbins): consider sending HTML formatted emails someday.
    self.email_template = template_helpers.MonorailTemplate(
        framework_constants.TEMPLATE_PATH + self._EMAIL_TEMPLATE,
        compress_whitespace=False, base_format=ezt.FORMAT_RAW)

    if self._LINK_ONLY_EMAIL_TEMPLATE:
      self.link_only_email_template = template_helpers.MonorailTemplate(
          framework_constants.TEMPLATE_PATH + self._LINK_ONLY_EMAIL_TEMPLATE,
          compress_whitespace=False, base_format=ezt.FORMAT_RAW)


def _MergeLinkedAccountReasons(addr_to_addrperm, addr_to_reasons):
  """Return an addr_reasons_dict where parents omit child accounts."""
  all_ids = set(addr_perm.user.user_id
                for addr_perm in addr_to_addrperm.values()
                if addr_perm.user)
  merged_ids = set()

  result = {}
  for addr, reasons in addr_to_reasons.items():
    addr_perm = addr_to_addrperm[addr]
    parent_id = addr_perm.user.linked_parent_id if addr_perm.user else None
    if parent_id and parent_id in all_ids:
      # The current user is a child account and the parent would be notified,
      # so only notify the parent.
      merged_ids.add(parent_id)
    else:
      result[addr] = reasons

  for addr, reasons in result.items():
    addr_perm = addr_to_addrperm[addr]
    if addr_perm.user and addr_perm.user.user_id in merged_ids:
      reasons.append(notify_reasons.REASON_LINKED_ACCOUNT)

  return result


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

  Args:
    group_reason_list: list of (addr_perm_list, reason) tuples.
    issue: Issue that was updated.
    body_link_only: string body of email with minimal information.
    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.
    detail_url: str direct link to the issue.
    seq_num: optional int sequence number of the comment.
    subject_prefix: optional string to customize the email subject line.
    compact_subject_prefix: optional string to customize the email subject line.

  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_to_addrperm = {}  # {email_address: AddrPerm object}
  addr_to_reasons = {}  # {email_address: [reason, ...]}
  for group, reason in group_reason_list:
    for memb_addr_perm in group:
      addr = memb_addr_perm.address
      addr_to_addrperm[addr] = memb_addr_perm
      addr_to_reasons.setdefault(addr, []).append(reason)

  addr_to_reasons = _MergeLinkedAccountReasons(
      addr_to_addrperm, addr_to_reasons)
  logging.info('addr_to_reasons is %r', addr_to_reasons)

  email_tasks = []
  for addr, reasons in addr_to_reasons.items():
    memb_addr_perm = addr_to_addrperm[addr]
    email_tasks.append(_MakeEmailWorkItem(
        memb_addr_perm, reasons, issue, body_link_only, body_for_non_members,
        body_for_members, project, hostport, commenter_view, detail_url,
        seq_num=seq_num, subject_prefix=subject_prefix,
        compact_subject_prefix=compact_subject_prefix))

  return email_tasks


def _TruncateBody(body):
  """Truncate body string if it exceeds size limit."""
  if len(body) > MAX_EMAIL_BODY_SIZE:
    logging.info('Truncate body since its size %d exceeds limit', len(body))
    return body[:MAX_EMAIL_BODY_SIZE] + '...'
  return body


def _GetNotifyRestrictedIssues(user_prefs, email, user):
  """Return the notify_restricted_issues pref or a calculated default value."""
  # If we explicitly set a pref for this address, use it.
  if user_prefs:
    for pref in user_prefs.prefs:
      if pref.name == NOTIFY_RESTRICTED_ISSUES_PREF_NAME:
        return pref.value

  # Mailing lists cannot visit the site, so if it visited, it is a person.
  if user and user.last_visit_timestamp:
    return NOTIFY_WITH_DETAILS

  # If it is a google.com mailing list, allow details for R-V-G issues.
  if email.endswith('@google.com'):
    return NOTIFY_WITH_DETAILS_GOOGLE

  # It might be a public mailing list, so don't risk leaking any details.
  return NOTIFY_WITH_LINK_ONLY


def ShouldUseLinkOnly(addr_perm, issue, always_detailed=False):
  """Return true when there is a risk of leaking a restricted issue.

  We send notifications that contain only a link to the issue with no other
  details about the change when:
  - The issue is R-V-G and the address may be a non-google.com mailing list, or
  - The issue is restricted with something other than R-V-G, and the user
     may be a mailing list, or
  - The user has a preference set.
  """
  if always_detailed:
    return False

  restrictions = permissions.GetRestrictions(issue, perm=permissions.VIEW)
  if not restrictions:
    return False

  pref = _GetNotifyRestrictedIssues(
      addr_perm.user_prefs, addr_perm.address, addr_perm.user)
  if pref == NOTIFY_WITH_DETAILS:
    return False
  if (pref == NOTIFY_WITH_DETAILS_GOOGLE and
      restrictions == ['restrict-view-google']):
    return False

  # If NOTIFY_WITH_LINK_ONLY or any unexpected value:
  return True


def _MakeEmailWorkItem(
    addr_perm, reasons, issue, body_link_only,
    body_for_non_members, body_for_members, project, hostport, commenter_view,
    detail_url, seq_num=None, subject_prefix=None, compact_subject_prefix=None):
  """Make one email task dict for one user, includes a detailed reason."""
  should_use_link_only = ShouldUseLinkOnly(
      addr_perm, issue, always_detailed=project.issue_notify_always_detailed)
  subject_format = (
      (subject_prefix or 'Issue ') +
      '%(local_id)d in %(project_name)s')
  if addr_perm.user and addr_perm.user.email_compact_subject:
    subject_format = (
        (compact_subject_prefix or '') +
        '%(project_name)s:%(local_id)d')

  subject = subject_format % {
    'local_id': issue.local_id,
    'project_name': issue.project_name,
    }
  if not should_use_link_only:
    subject += ': ' + issue.summary

  footer = _MakeNotificationFooter(reasons, addr_perm.reply_perm, hostport)
  footer = six.ensure_str(footer)
  if should_use_link_only:
    body = _TruncateBody(body_link_only) + footer
  elif addr_perm.is_member:
    logging.info('got member %r, sending body for members', addr_perm.address)
    body = _TruncateBody(body_for_members) + footer
  else:
    logging.info(
        'got non-member %r, sending body for non-members', addr_perm.address)
    body = _TruncateBody(body_for_non_members) + footer
  logging.info('sending message footer:\n%r', footer)

  can_reply_to = (
      addr_perm.reply_perm != notify_reasons.REPLY_NOT_ALLOWED and
      project.process_inbound_email)
  from_addr = emailfmt.FormatFromAddr(
    project, commenter_view=commenter_view, reveal_addr=addr_perm.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(
    addr_perm.address, subject, seq_num,
    '%s@%s' % (project.project_name, emailfmt.MailDomain()))
  # We use markup to display a convenient link that takes users directly to the
  # issue without clicking on the email.
  html_body = None
  template = HTML_BODY_WITH_GMAIL_ACTION_TEMPLATE
  if addr_perm.user and not addr_perm.user.email_view_widget:
    template = HTML_BODY_WITHOUT_GMAIL_ACTION_TEMPLATE
  body_with_tags = _AddHTMLTags(six.ensure_text(body))
  # Escape single quotes which are occasionally used to contain HTML
  # attributes and event handler definitions.
  body_with_tags = body_with_tags.replace("'", '&#x27;')
  html_body = template % {
      'url': detail_url,
      'body': body_with_tags,
      }
  return dict(
    to=addr_perm.address, subject=subject, body=body, 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 = _AutolinkBody(body)

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


def _AutolinkBody(body):
  """Convert text that looks like URLs into <a href=...>.

  This uses autolink.py, but it does not register all the autolink components
  because some of them depend on the current user's permissions which would
  not make sense for an email body that will be sent to several different users.
  """
  email_autolink = autolink.Autolink()
  email_autolink.RegisterComponent(
      '01-linkify-user-profiles-or-mailto',
      lambda request, mr: None,
      lambda _mr, match: [match.group(0)],
      {autolink_constants.IS_IMPLIED_EMAIL_RE: autolink.LinkifyEmail})
  email_autolink.RegisterComponent(
      '02-linkify-full-urls',
      lambda request, mr: None,
      lambda mr, match: None,
      {autolink_constants.IS_A_LINK_RE: autolink.Linkify})
  email_autolink.RegisterComponent(
      '03-linkify-shorthand',
      lambda request, mr: None,
      lambda mr, match: None,
      {autolink_constants.IS_A_SHORT_LINK_RE: autolink.Linkify,
       autolink_constants.IS_A_NUMERIC_SHORT_LINK_RE: autolink.Linkify,
       autolink_constants.IS_IMPLIED_LINK_RE: autolink.Linkify,
       })

  input_run = template_helpers.TextRun(body)
  output_runs = email_autolink.MarkupAutolinks(
      None, [input_run], autolink.SKIP_LOOKUPS)
  output_strings = [run.FormatForHTMLEmail() for run in output_runs]
  return ''.join(output_strings)


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 == notify_reasons.REPLY_MAY_COMMENT:
    lines.extend(['', 'Reply to this email to add a comment.'])
  elif reply_perm == notify_reasons.REPLY_MAY_UPDATE:
    lines.extend(['', 'Reply to this email to add a comment or make updates.'])

  return '\n'.join(lines)
