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

"""Code to support project and user activies pages."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import sql
from framework import template_helpers
from framework import timestr
from project import project_views
from mrproto import tracker_pb2
from tracker import tracker_helpers
from tracker import tracker_views

UPDATES_PER_PAGE = 50
MAX_UPDATES_PER_PAGE = 200


class ActivityView(template_helpers.PBProxy):
  """EZT-friendly wrapper for Activities."""

  _TITLE_TEMPLATE = template_helpers.MonorailTemplate(
      framework_constants.TEMPLATE_PATH + 'features/activity-title.ezt',
      compress_whitespace=True, base_format=ezt.FORMAT_HTML)

  _BODY_TEMPLATE = template_helpers.MonorailTemplate(
      framework_constants.TEMPLATE_PATH + 'features/activity-body.ezt',
      compress_whitespace=True, base_format=ezt.FORMAT_HTML)

  def __init__(
      self, pb, mr, prefetched_issues, users_by_id,
      prefetched_projects, prefetched_configs,
      autolink=None, all_ref_artifacts=None, ending=None, highlight=None):
    """Constructs an ActivityView out of an Activity protocol buffer.

    Args:
      pb: an IssueComment or Activity protocol buffer.
      mr: HTTP request info, used by the artifact autolink.
      prefetched_issues: dictionary of the issues for the comments being shown.
      users_by_id: dict {user_id: UserView} for all relevant users.
      prefetched_projects: dict {project_id: project} including all the projects
          that we might need.
      prefetched_configs: dict {project_id: config} for those projects.
      autolink: Autolink instance.
      all_ref_artifacts: list of all artifacts in the activity stream.
      ending: ending type for activity titles, 'in_project' or 'by_user'
      highlight: what to highlight in the middle column on user updates pages
          i.e. 'project', 'user', or None
    """
    template_helpers.PBProxy.__init__(self, pb)

    activity_type = 'ProjectIssueUpdate'  # TODO(jrobbins): more types

    self.comment = None
    self.issue = None
    self.field_changed = None
    self.multiple_fields_changed = ezt.boolean(False)
    self.project = None
    self.user = None
    self.timestamp = time.time()  # Bogus value makes bad ones highly visible.

    if isinstance(pb, tracker_pb2.IssueComment):
      self.timestamp = pb.timestamp
      issue = prefetched_issues[pb.issue_id]
      if self.timestamp == issue.opened_timestamp:
        issue_change_id = None  # This comment is the description.
      else:
        issue_change_id = pb.timestamp  # instead of seq num.

      self.comment = tracker_views.IssueCommentView(
          mr.project_name, pb, users_by_id, autolink,
          all_ref_artifacts, mr, issue)

      # TODO(jrobbins): pass effective_ids of the commenter so that they
      # can be identified as a project member or not.
      config = prefetched_configs[issue.project_id]
      self.issue = tracker_views.IssueView(issue, users_by_id, config)
      self.user = self.comment.creator
      project = prefetched_projects[issue.project_id]
      self.project_name = project.project_name
      self.project = project_views.ProjectView(project)

    else:
      logging.warning('unknown activity object %r', pb)

    nested_page_data = {
        'activity_type': activity_type,
        'issue_change_id': issue_change_id,
        'comment': self.comment,
        'issue': self.issue,
        'project': self.project,
        'user': self.user,
        'timestamp': self.timestamp,
        'ending_type': ending,
        }

    self.escaped_title = self._TITLE_TEMPLATE.GetResponse(
        nested_page_data).strip()
    self.escaped_body = self._BODY_TEMPLATE.GetResponse(
        nested_page_data).strip()

    if autolink is not None and all_ref_artifacts is not None:
      # TODO(jrobbins): actually parse the comment text.  Actually render runs.
      runs = autolink.MarkupAutolinks(
          mr, [template_helpers.TextRun(self.escaped_body)], all_ref_artifacts)
      self.escaped_body = ''.join(run.content for run in runs)

    self.date_bucket, self.date_relative = timestr.GetHumanScaleDate(
        self.timestamp)
    time_tuple = time.localtime(self.timestamp)
    self.date_tooltip = time.asctime(time_tuple)

    # We always highlight the user for starring activities
    if activity_type.startswith('UserStar'):
      self.highlight = 'user'
    else:
      self.highlight = highlight


def GatherUpdatesData(
    services, mr, project_ids=None, user_ids=None, ending=None,
    updates_page_url=None, autolink=None, highlight=None):
  """Gathers and returns updates data.

  Args:
    services: Connections to backend services.
    mr: HTTP request info, used by the artifact autolink.
    project_ids: List of project IDs we want updates for.
    user_ids: List of user IDs we want updates for.
    ending: Ending type for activity titles, 'in_project' or 'by_user'.
    updates_page_url: The URL that will be used to create pagination links from.
    autolink: Autolink instance.
    highlight: What to highlight in the middle column on user updates pages
        i.e. 'project', 'user', or None.
  """
  # num should be non-negative number
  num = mr.GetPositiveIntParam('num', UPDATES_PER_PAGE)
  num = min(num, MAX_UPDATES_PER_PAGE)

  updates_data = {
      'no_stars': None,
      'no_activities': None,
      'pagination': None,
      'updates_data': None,
      'ending_type': ending,
      }

  if not user_ids and not project_ids:
    updates_data['no_stars'] = ezt.boolean(True)
    return updates_data

  ascending = bool(mr.after)
  with mr.profiler.Phase('get activities'):
    comments = services.issue.GetIssueActivity(mr.cnxn, num=num,
        before=mr.before, after=mr.after, project_ids=project_ids,
        user_ids=user_ids, ascending=ascending)
    # Filter the comments based on permission to view the issue.
    # TODO(jrobbins): push permission checking in the query so that
    # pagination pages never become underfilled, or use backends to shard.
    # TODO(jrobbins): come back to this when I implement private comments.
    # TODO(jrobbins): it would be better if we could just get the dict directly.
    prefetched_issues_list = services.issue.GetIssues(
        mr.cnxn, {c.issue_id for c in comments})
    prefetched_issues = {
        issue.issue_id: issue for issue in prefetched_issues_list}
    needed_project_ids = {issue.project_id for issue
        in prefetched_issues_list}
    prefetched_projects = services.project.GetProjects(
        mr.cnxn, needed_project_ids)
    prefetched_configs = services.config.GetProjectConfigs(
        mr.cnxn, needed_project_ids)
    viewable_issues_list = tracker_helpers.FilterOutNonViewableIssues(
        mr.auth.effective_ids, mr.auth.user_pb, prefetched_projects,
        prefetched_configs, prefetched_issues_list)
    viewable_iids = {issue.issue_id for issue in viewable_issues_list}
    comments = [
        c for c in comments if c.issue_id in viewable_iids]
    if ascending:
      comments.reverse()

  amendment_user_ids = []
  for comment in comments:
    for amendment in comment.amendments:
      amendment_user_ids.extend(amendment.added_user_ids)
      amendment_user_ids.extend(amendment.removed_user_ids)

  users_by_id = framework_views.MakeAllUserViews(
      mr.cnxn, services.user, [c.user_id for c in comments],
      amendment_user_ids)
  framework_views.RevealAllEmailsToMembers(
      mr.cnxn, services, mr.auth, users_by_id, mr.project)

  num_results_returned = len(comments)
  displayed_activities = comments[:UPDATES_PER_PAGE]

  if not num_results_returned:
    updates_data['no_activities'] = ezt.boolean(True)
    return updates_data

  # Get all referenced artifacts first
  all_ref_artifacts = None
  if autolink is not None:
    content_list = []
    for activity in comments:
      content_list.append(activity.content)

    all_ref_artifacts = autolink.GetAllReferencedArtifacts(
        mr, content_list)

  # Now process content and gather activities
  today = []
  yesterday = []
  pastweek = []
  pastmonth = []
  thisyear = []
  older = []

  with mr.profiler.Phase('rendering activities'):
    for activity in displayed_activities:
      entry = ActivityView(
          activity, mr, prefetched_issues, users_by_id,
          prefetched_projects, prefetched_configs,
          autolink=autolink, all_ref_artifacts=all_ref_artifacts, ending=ending,
          highlight=highlight)

      if entry.date_bucket == 'Today':
        today.append(entry)
      elif entry.date_bucket == 'Yesterday':
        yesterday.append(entry)
      elif entry.date_bucket == 'Last 7 days':
        pastweek.append(entry)
      elif entry.date_bucket == 'Last 30 days':
        pastmonth.append(entry)
      elif entry.date_bucket == 'Earlier this year':
        thisyear.append(entry)
      elif entry.date_bucket == 'Before this year':
        older.append(entry)

  new_after = None
  new_before = None
  if displayed_activities:
    new_after = displayed_activities[0].timestamp
    new_before = displayed_activities[-1].timestamp

  prev_url = None
  next_url = None
  if updates_page_url:
    list_servlet_rel_url = updates_page_url.split('/')[-1]
    recognized_params = [(name, mr.GetParam(name))
                         for name in framework_helpers.RECOGNIZED_PARAMS]
    if displayed_activities and (mr.before or mr.after):
      prev_url = framework_helpers.FormatURL(
          recognized_params, list_servlet_rel_url, after=new_after)
    if mr.after or len(comments) > UPDATES_PER_PAGE:
      next_url = framework_helpers.FormatURL(
          recognized_params, list_servlet_rel_url, before=new_before)

  if prev_url or next_url:
    pagination = template_helpers.EZTItem(
        start=None, last=None, prev_url=prev_url, next_url=next_url,
        reload_url=None, visible=ezt.boolean(True), total_count=None)
  else:
    pagination = None

  updates_data.update({
      'no_activities': ezt.boolean(False),
      'pagination': pagination,
      'updates_data': template_helpers.EZTItem(
          today=today, yesterday=yesterday, pastweek=pastweek,
          pastmonth=pastmonth, thisyear=thisyear, older=older),
      })

  return updates_data
