# 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

"""Cron and task handlers for email notifications of issue date value arrival.

If an issue has a date-type custom field, and that custom field is configured
to perform an action when that date arrives, then this cron handler and the
associated tasks carry out those actions on that issue.
"""

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import logging
import time

import ezt

import settings

from features import notify_helpers
from features import notify_reasons
from framework import cloud_tasks_helpers
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import jsonfeed
from framework import permissions
from framework import timestr
from framework import urls
from proto import tracker_pb2
from tracker import tracker_bizobj
from tracker import tracker_helpers
from tracker import tracker_views


TEMPLATE_PATH = framework_constants.TEMPLATE_PATH


class DateActionCron(jsonfeed.FlaskInternalTask):
  """Find and process issues with date-type values that arrived today."""

  def HandleRequest(self, mr):
    """Find issues with date-type-fields that arrived and spawn tasks."""
    highest_iid_so_far = 0
    capped = True
    timestamp_min, timestamp_max = _GetTimestampRange(int(time.time()))
    left_joins = [
        ('Issue2FieldValue ON Issue.id = Issue2FieldValue.issue_id', []),
        ('FieldDef ON Issue2FieldValue.field_id = FieldDef.id', []),
        ]
    where = [
        ('FieldDef.field_type = %s', ['date_type']),
        ('FieldDef.date_action IN (%s,%s)',
         ['ping_owner_only', 'ping_participants']),
        ('Issue2FieldValue.date_value >= %s', [timestamp_min]),
        ('Issue2FieldValue.date_value < %s', [timestamp_max]),
        ]
    order_by = [
        ('Issue.id', []),
        ]
    while capped:
      chunk_issue_ids, capped = self.services.issue.RunIssueQuery(
          mr.cnxn, left_joins,
          where + [('Issue.id > %s', [highest_iid_so_far])], order_by)
      if chunk_issue_ids:
        logging.info('chunk_issue_ids = %r', chunk_issue_ids)
        highest_iid_so_far = max(highest_iid_so_far, max(chunk_issue_ids))
        for issue_id in chunk_issue_ids:
          self.EnqueueDateAction(issue_id)

  def EnqueueDateAction(self, issue_id):
    """Create a task to notify users that an issue's date has arrived.

    Args:
      issue_id: int ID of the issue that was changed.

    Returns nothing.
    """
    params = {'issue_id': issue_id}
    task = cloud_tasks_helpers.generate_simple_task(
        urls.ISSUE_DATE_ACTION_TASK + '.do', params)
    cloud_tasks_helpers.create_task(task)

  def GetDateActionCron(self, **kwargs):
    return self.handler(**kwargs)


def _GetTimestampRange(now):
  """Return a (min, max) timestamp range for today."""
  timestamp_min = (now // framework_constants.SECS_PER_DAY *
                   framework_constants.SECS_PER_DAY)
  timestamp_max = timestamp_min + framework_constants.SECS_PER_DAY
  return timestamp_min, timestamp_max


class IssueDateActionTask(notify_helpers.NotifyTaskBase):
  """JSON servlet that notifies appropriate users after an issue change."""

  _EMAIL_TEMPLATE = 'features/auto-ping-email.ezt'
  _LINK_ONLY_EMAIL_TEMPLATE = (
      'tracker/issue-change-notification-email-link-only.ezt')

  def HandleRequest(self, mr):
    """Process the task to process an issue date action.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format which is useful just for debugging.
      The main goal is the side-effect of sending emails.
    """
    issue_id = mr.GetPositiveIntParam('issue_id')
    issue = self.services.issue.GetIssue(mr.cnxn, issue_id, use_cache=False)
    project = self.services.project.GetProject(mr.cnxn, issue.project_id)
    hostport = framework_helpers.GetHostPort(project_name=project.project_name)
    config = self.services.config.GetProjectConfig(mr.cnxn, issue.project_id)
    pings = self._CalculateIssuePings(issue, config)
    if not pings:
      logging.warning('Issue %r has no dates to ping afterall?', issue_id)
      return
    comment = self._CreatePingComment(mr.cnxn, issue, pings, hostport)
    starrer_ids = self.services.issue_star.LookupItemStarrers(
        mr.cnxn, issue.issue_id)

    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user,
        tracker_bizobj.UsersInvolvedInIssues([issue]),
        tracker_bizobj.UsersInvolvedInComment(comment),
        starrer_ids)
    logging.info('users_by_id is %r', users_by_id)
    tasks = self._MakeEmailTasks(
      mr.cnxn, issue, project, config, comment, starrer_ids,
      hostport, users_by_id, pings)

    notified = notify_helpers.AddAllEmailTasks(tasks)
    return {
        'notified': notified,
        }

  def _CreatePingComment(self, cnxn, issue, pings, hostport):
    """Create an issue comment saying that some dates have arrived."""
    content = '\n'.join(self._FormatPingLine(ping) for ping in pings)
    author_email_addr = '%s@%s' % (settings.date_action_ping_author, hostport)
    date_action_user_id = self.services.user.LookupUserID(
        cnxn, author_email_addr, autocreate=True)
    comment = self.services.issue.CreateIssueComment(
        cnxn, issue, date_action_user_id, content)
    return comment

  def _MakeEmailTasks(
      self, cnxn, issue, project, config, comment, starrer_ids,
      hostport, users_by_id, pings):
    """Return a list of dicts for tasks to notify people."""
    detail_url = framework_helpers.IssueCommentURL(
        hostport, project, issue.local_id, seq_num=comment.sequence)
    fields = sorted((field_def for (field_def, _date_value) in pings),
                    key=lambda fd: fd.field_name)
    email_data = {
        'issue': tracker_views.IssueView(issue, users_by_id, config),
        'summary': issue.summary,
        'ping_comment_content': comment.content,
        'detail_url': detail_url,
        'fields': fields,
        }

    # Generate three versions of email body with progressively more info.
    body_link_only = self.link_only_email_template.GetResponse(
      {'detail_url': detail_url, 'was_created': ezt.boolean(False)})
    body_for_non_members = self.email_template.GetResponse(email_data)
    framework_views.RevealAllEmails(users_by_id)
    body_for_members = self.email_template.GetResponse(email_data)
    logging.info('body for non-members is:\n%r' % body_for_non_members)
    logging.info('body for members is:\n%r' % body_for_members)

    contributor_could_view = permissions.CanViewIssue(
        set(), permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET,
        project, issue)

    group_reason_list = notify_reasons.ComputeGroupReasonList(
        cnxn, self.services, project, issue, config, users_by_id,
        [], contributor_could_view, starrer_ids=starrer_ids,
        commenter_in_project=True, include_subscribers=False,
        include_notify_all=False,
        starrer_pref_check_function=lambda u: u.notify_starred_ping)

    commenter_view = users_by_id[comment.user_id]
    email_tasks = notify_helpers.MakeBulletedEmailWorkItems(
        group_reason_list, issue, body_link_only, body_for_non_members,
        body_for_members, project, hostport, commenter_view, detail_url,
        seq_num=comment.sequence, subject_prefix='Follow up on issue ',
        compact_subject_prefix='Follow up ')

    return email_tasks

  def _CalculateIssuePings(self, issue, config):
    """Return a list of (field, timestamp) pairs for dates that should ping."""
    timestamp_min, timestamp_max = _GetTimestampRange(int(time.time()))
    arrived_dates_by_field_id = {
        fv.field_id: fv.date_value
        for fv in issue.field_values
        if timestamp_min <= fv.date_value < timestamp_max}
    logging.info('arrived_dates_by_field_id = %r', arrived_dates_by_field_id)
    # TODO(jrobbins): Lookup field defs regardless of project_id to better
    # handle foreign fields in issues that have been moved between projects.
    pings = [
      (field, arrived_dates_by_field_id[field.field_id])
      for field in config.field_defs
      if (field.field_id in arrived_dates_by_field_id and
          field.date_action in (tracker_pb2.DateAction.PING_OWNER_ONLY,
                                tracker_pb2.DateAction.PING_PARTICIPANTS))]

    # TODO(jrobbins): For now, assume all pings apply only to open issues.
    # Later, allow each date action to specify whether it applies to open
    # issues or all issues.
    means_open = tracker_helpers.MeansOpenInProject(
        tracker_bizobj.GetStatus(issue), config)
    pings = [ping for ping in pings if means_open]

    pings = sorted(pings, key=lambda ping: ping[0].field_name)
    return pings

  def _FormatPingLine(self, ping):
    """Return a one-line string describing the date that arrived."""
    field, timestamp = ping
    date_str = timestr.TimestampToDateWidgetStr(timestamp)
    return 'The %s date has arrived: %s' % (field.field_name, date_str)

  def PostIssueDateActionTask(self, **kwargs):
    return self.handler(**kwargs)
