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

"""A class to display a paginated list of project members.

This page lists owners, members, and contribtors.  For each
member, we display their username, permission system role + extra
perms, and notes on their involvement in the project.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from businesslogic import work_env
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import paginate
from framework import permissions
from framework import servlet
from framework import urls
from project import project_helpers
from project import project_views

MEMBERS_PER_PAGE = 50


class PeopleList(servlet.Servlet):
  """People list page shows a paginated list of project members."""

  _PAGE_TEMPLATE = 'project/people-list-page.ezt'
  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PEOPLE

  def AssertBasePermission(self, mr):
    super(PeopleList, self).AssertBasePermission(mr)
    # For now, contributors who cannot view other contributors are further
    # restricted from viewing any part of the member list or detail pages.
    if not permissions.CanViewContributorList(mr, mr.project):
      raise permissions.PermissionException(
          'User is not allowed to view the project people list')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    all_members = (mr.project.owner_ids +
                   mr.project.committer_ids +
                   mr.project.contributor_ids)

    with mr.profiler.Phase('gathering members on this page'):
      users_by_id = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, all_members)
      framework_views.RevealAllEmailsToMembers(
          mr.cnxn, self.services, mr.auth, users_by_id, mr.project)

    # TODO(jrobbins): re-implement FindUntrustedGroups()
    untrusted_user_group_proxies = []

    with mr.profiler.Phase('gathering commitments (notes)'):
      project_commitments = self.services.project.GetProjectCommitments(
          mr.cnxn, mr.project_id)

    with mr.profiler.Phase('gathering autocomple exclusion ids'):
      group_ids = set(self.services.usergroup.DetermineWhichUserIDsAreGroups(
        mr.cnxn, all_members))
      (ac_exclusion_ids, no_expand_ids
       ) = self.services.project.GetProjectAutocompleteExclusion(
          mr.cnxn, mr.project_id)

    with mr.profiler.Phase('making member views'):
      owner_views = self._MakeMemberViews(
          mr.auth.user_id, users_by_id, mr.project.owner_ids, mr.project,
          project_commitments, ac_exclusion_ids, no_expand_ids, group_ids)
      committer_views = self._MakeMemberViews(
          mr.auth.user_id, users_by_id, mr.project.committer_ids, mr.project,
          project_commitments, ac_exclusion_ids, no_expand_ids, group_ids)
      contributor_views = self._MakeMemberViews(
          mr.auth.user_id, users_by_id, mr.project.contributor_ids, mr.project,
          project_commitments, ac_exclusion_ids, no_expand_ids, group_ids)
      all_member_views = owner_views + committer_views + contributor_views

    url_params = [(name, mr.GetParam(name)) for name in
                  framework_helpers.RECOGNIZED_PARAMS]
    pagination = paginate.ArtifactPagination(
        all_member_views, mr.GetPositiveIntParam('num', MEMBERS_PER_PAGE),
        mr.GetPositiveIntParam('start'), mr.project_name, urls.PEOPLE_LIST,
        url_params=url_params)

    offer_membership_editing = permissions.CanEditProjectConfig(
        mr, self.services)

    check_abandonment = permissions.ShouldCheckForAbandonment(mr)

    newly_added_views = [mv for mv in all_member_views
                         if str(mv.user.user_id) in mr.GetParam('new', [])]

    return {
        'pagination': pagination,
        'subtab_mode': None,
        'offer_membership_editing': ezt.boolean(offer_membership_editing),
        'initial_add_members': '',
        'initially_expand_form': ezt.boolean(False),
        'untrusted_user_groups': untrusted_user_group_proxies,
        'check_abandonment': ezt.boolean(check_abandonment),
        'total_num_owners': len(mr.project.owner_ids),
        'newly_added_views': newly_added_views,
        'is_hotlist': ezt.boolean(False),
        }

  def GatherHelpData(self, mr, page_data):
    """Return a dict of values to drive on-page user help.

    Args:
      mr: common information parsed from the HTTP request.
      page_data: Dictionary of base and page template data.

    Returns:
      A dict of values to drive on-page user help, to be added to page_data.
    """
    help_data = super(PeopleList, self).GatherHelpData(mr, page_data)
    with work_env.WorkEnv(mr, self.services) as we:
      userprefs = we.GetUserPrefs(mr.auth.user_id)
    dismissed = [
        pv.name for pv in userprefs.prefs if pv.value == 'true']
    if (mr.auth.user_id and
        not framework_bizobj.UserIsInProject(
            mr.project, mr.auth.effective_ids) and
        'how_to_join_project' not in dismissed):
      help_data['cue'] = 'how_to_join_project'

    return help_data

  def _MakeMemberViews(
      self, logged_in_user_id, users_by_id, member_ids, project,
      project_commitments, ac_exclusion_ids, no_expand_ids, group_ids):
    """Return a sorted list of MemberViews for display by EZT."""
    member_views = [
        project_views.MemberView(
            logged_in_user_id, member_id, users_by_id[member_id], project,
            project_commitments,
            ac_exclusion=(member_id in ac_exclusion_ids),
            no_expand=(member_id in no_expand_ids),
            is_group=(member_id in group_ids))
        for member_id in member_ids]
    member_views.sort(key=lambda mv: mv.user.email)
    return member_views

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    permit_edit = permissions.CanEditProjectConfig(mr, self.services)
    if not permit_edit:
      raise permissions.PermissionException(
          'User is not permitted to edit project membership')

    if 'addbtn' in post_data:
      return self.ProcessAddMembers(mr, post_data)
    elif 'removebtn' in post_data:
      return self.ProcessRemoveMembers(mr, post_data)

  def ProcessAddMembers(self, mr, post_data):
    """Process the user's request to add members.

    Args:
      mr: common information parsed from the HTTP request.
      post_data: dictionary of form data.

    Returns:
      String URL to redirect the user to after processing.
    """
    # 1. Parse and validate user input.
    new_member_ids = project_helpers.ParseUsernames(
        mr.cnxn, self.services.user, post_data.get('addmembers'))
    role = post_data['role']

    (owner_ids, committer_ids,
     contributor_ids) = project_helpers.MembersWithGivenIDs(
        mr.project, new_member_ids, role)

    total_people = len(owner_ids) + len(committer_ids) + len(contributor_ids)
    if total_people > framework_constants.MAX_PROJECT_PEOPLE:
      mr.errors.addmembers = (
          'Too many project members.  The combined limit is %d.' %
          framework_constants.MAX_PROJECT_PEOPLE)

    # 2. Call services layer to save changes.
    if not mr.errors.AnyErrors():
      self.services.project.UpdateProjectRoles(
          mr.cnxn, mr.project.project_id,
          owner_ids, committer_ids, contributor_ids)

    # 3. Determine the next page in the UI flow.
    if mr.errors.AnyErrors():
      add_members_str = post_data.get('addmembers', '')
      self.PleaseCorrect(
          mr, initial_add_members=add_members_str, initially_expand_form=True)
    else:
      return framework_helpers.FormatAbsoluteURL(
          mr, urls.PEOPLE_LIST, saved=1, ts=int(time.time()),
          new=','.join([str(u) for u in new_member_ids]))

  def ProcessRemoveMembers(self, mr, post_data):
    """Process the user's request to remove members.

    Args:
      mr: common information parsed from the HTTP request.
      post_data: dictionary of form data.

    Returns:
      String URL to redirect the user to after processing.
    """
    # 1. Parse and validate user input.
    remove_strs = post_data.getlist('remove')
    logging.info('remove_strs = %r', remove_strs)
    remove_ids = set(
        self.services.user.LookupUserIDs(mr.cnxn, remove_strs).values())
    (owner_ids, committer_ids,
     contributor_ids) = project_helpers.MembersWithoutGivenIDs(
        mr.project, remove_ids)

    # 2. Call services layer to save changes.
    self.services.project.UpdateProjectRoles(
        mr.cnxn, mr.project.project_id, owner_ids, committer_ids,
        contributor_ids)

    # 3. Determine the next page in the UI flow.
    return framework_helpers.FormatAbsoluteURL(
        mr, urls.PEOPLE_LIST, saved=1, ts=int(time.time()))

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

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