# 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

"""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 proto 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.warn('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
