# Copyright 2016 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 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 proto 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.FlaskInternalTask):
  """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)
  if isinstance(footer, six.text_type):
    footer = footer.encode('utf-8')
  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(body.decode('utf-8'))
  # Escape single quotes which are occasionally used to contain HTML
  # attributes and event handler definitions.
  body_with_tags = body_with_tags.replace("'", '&#39;')
  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)
