# 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


# TODO: change to FlaskInternalTask when convert to flask
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)
  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)
