# 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 details about each project member."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from framework import exceptions
from framework import framework_bizobj
from framework import framework_helpers
from framework import framework_views
from framework import permissions
from framework import servlet
from framework import template_helpers
from framework import urls
from project import project_helpers
from project import project_views

CHECKBOX_PERMS = [
    permissions.VIEW,
    permissions.COMMIT,
    permissions.CREATE_ISSUE,
    permissions.ADD_ISSUE_COMMENT,
    permissions.EDIT_ISSUE,
    permissions.EDIT_ISSUE_OWNER,
    permissions.EDIT_ISSUE_SUMMARY,
    permissions.EDIT_ISSUE_STATUS,
    permissions.EDIT_ISSUE_CC,
    permissions.DELETE_ISSUE,
    permissions.DELETE_OWN,
    permissions.DELETE_ANY,
    permissions.EDIT_ANY_MEMBER_NOTES,
    ]


class PeopleDetail(servlet.Servlet):
  """People detail page documents one partipant's involvement in a project."""

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

  def AssertBasePermission(self, mr):
    """Check that the user is allowed to access this servlet."""
    super(PeopleDetail, self).AssertBasePermission(mr)
    member_id = self.ValidateMemberID(mr.cnxn, mr.specified_user_id, mr.project)
    # 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) and
        member_id != mr.auth.user_id):
      raise permissions.PermissionException(
          'User is not allowed to view other people\'s details')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""

    member_id = self.ValidateMemberID(mr.cnxn, mr.specified_user_id, mr.project)
    group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups(
        mr.cnxn, [member_id])
    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, [member_id])
    framework_views.RevealAllEmailsToMembers(
        mr.cnxn, self.services, mr.auth, users_by_id, mr.project)

    project_commitments = self.services.project.GetProjectCommitments(
        mr.cnxn, mr.project_id)
    (ac_exclusion_ids, no_expand_ids
     ) = self.services.project.GetProjectAutocompleteExclusion(
        mr.cnxn, mr.project_id)
    member_view = project_views.MemberView(
        mr.auth.user_id, member_id, users_by_id[member_id], mr.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))

    member_user = self.services.user.GetUser(mr.cnxn, member_id)
    # This ignores indirect memberships, which is ok because we are viewing
    # the page for a member directly involved in the project
    role_perms = permissions.GetPermissions(
        member_user, {member_id}, mr.project)

    # TODO(jrobbins): clarify in the UI which permissions are built-in to
    # the user's direct role, vs. which are granted via a group membership,
    # vs. which ones are extra_perms that have been added specifically for
    # this user.
    member_perms = template_helpers.EZTItem()
    for perm in CHECKBOX_PERMS:
      setattr(member_perms, perm,
              ezt.boolean(role_perms.HasPerm(perm, member_id, mr.project)))

    displayed_extra_perms = [perm for perm in member_view.extra_perms
                             if perm not in CHECKBOX_PERMS]

    viewing_self = mr.auth.user_id == member_id
    warn_abandonment = (viewing_self and
                        permissions.ShouldCheckForAbandonment(mr))

    return {
        'subtab_mode': None,
        'member': member_view,
        'role_perms': role_perms,
        'member_perms': member_perms,
        'displayed_extra_perms': displayed_extra_perms,
        'offer_edit_perms': ezt.boolean(self.CanEditPerms(mr)),
        'offer_edit_member_notes': ezt.boolean(
            self.CanEditMemberNotes(mr, member_id)),
        'offer_remove_role': ezt.boolean(self.CanRemoveRole(mr, member_id)),
        'expand_perms': ezt.boolean(mr.auth.user_pb.keep_people_perms_open),
        'warn_abandonment': ezt.boolean(warn_abandonment),
        'total_num_owners': len(mr.project.owner_ids),
        }

  def ValidateMemberID(self, cnxn, member_id, project):
    """Lookup a project member by user_id.

    Args:
      cnxn: connection to SQL database.
      member_id: int user_id, same format as user profile page.
      project: the current Project PB.

    Returns:
      The user ID of the project member. Raises an exception if the username
      cannot be looked up, or if that user is not in the project.
    """
    if not member_id:
      self.abort(404, 'project member not specified')

    member_username = None
    try:
      member_username = self.services.user.LookupUserEmail(cnxn, member_id)
    except exceptions.NoSuchUserException:
      logging.info('user_id %s not found', member_id)

    if not member_username:
      logging.info('There is no such user id %r', member_id)
      self.abort(404, 'project member not found')

    if not framework_bizobj.UserIsInProject(project, {member_id}):
      logging.info('User %r is not a member of %r',
                   member_username, project.project_name)
      self.abort(404, 'project member not found')

    return member_id

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    # 1. Parse and validate user input.
    user_id, role, extra_perms, notes, ac_exclusion, no_expand = (
        self.ParsePersonData(mr, post_data))
    member_id = self.ValidateMemberID(mr.cnxn, user_id, mr.project)

    # 2. Call services layer to save changes.
    if 'remove' in post_data:
      self.ProcessRemove(mr, member_id)
    else:
      self.ProcessSave(
          mr, role, extra_perms, notes, member_id, ac_exclusion, no_expand)

    # 3. Determine the next page in the UI flow.
    if 'remove' in post_data:
      return framework_helpers.FormatAbsoluteURL(
          mr, urls.PEOPLE_LIST, saved=1, ts=int(time.time()))
    else:
      return framework_helpers.FormatAbsoluteURL(
          mr, urls.PEOPLE_DETAIL, u=user_id, saved=1, ts=int(time.time()))

  def ProcessRemove(self, mr, member_id):
    """Process the posted form when the user pressed 'Remove'."""
    if not self.CanRemoveRole(mr, member_id):
      raise permissions.PermissionException(
          'User is not allowed to remove this member from the project')

    self.RemoveRole(mr.cnxn, mr.project, member_id)

  def ProcessSave(
      self, mr, role, extra_perms, notes, member_id, ac_exclusion,
      no_expand):
    """Process the posted form when the user pressed 'Save'."""
    if (not self.CanEditPerms(mr) and
        not self.CanEditMemberNotes(mr, member_id)):
      raise permissions.PermissionException(
          'User is not allowed to edit people in this project')

    if self.CanEditPerms(mr):
      self.services.project.UpdateExtraPerms(
          mr.cnxn, mr.project_id, member_id, extra_perms)
      self.UpdateRole(mr.cnxn, mr.project, role, member_id)

    if self.CanEditMemberNotes(mr, member_id):
      self.services.project.UpdateCommitments(
          mr.cnxn, mr.project_id, member_id, notes)

    if self.CanEditPerms(mr):
      self.services.project.UpdateProjectAutocompleteExclusion(
          mr.cnxn, mr.project_id, member_id, ac_exclusion, no_expand)

  def CanEditMemberNotes(self, mr, member_id):
    """Return true if the logged in user can edit the current user's notes."""
    return (self.CheckPerm(mr, permissions.EDIT_ANY_MEMBER_NOTES) or
            member_id == mr.auth.user_id)

  def CanEditPerms(self, mr):
    """Return true if the logged in user can edit the current user's perms."""
    return self.CheckPerm(mr, permissions.EDIT_PROJECT)

  def CanRemoveRole(self, mr, member_id):
    """Return true if the logged in user can remove the current user's role."""
    return (self.CheckPerm(mr, permissions.EDIT_PROJECT) or
            member_id == mr.auth.user_id)

  def ParsePersonData(self, mr, post_data):
    """Parse the POST data for a project member.

    Args:
      mr: common information parsed from the user's request.
      post_data: dictionary of lists of values for each HTML
          form field.

    Returns:
      A tuple with user_id, role, extra_perms, and notes.
    """
    if not mr.specified_user_id:
      raise exceptions.InputException('Field user_id is missing')

    role = post_data.get('role', '').lower()
    extra_perms = []
    for ep in post_data.getlist('extra_perms'):
      perm = framework_bizobj.CanonicalizeLabel(ep)
      # Perms with leading underscores are reserved.
      perm = perm.strip('_')
      if perm:
        extra_perms.append(perm)

    notes = post_data.get('notes', '').strip()
    ac_exclusion = not post_data.get('ac_include', False)
    no_expand = not post_data.get('ac_expand', False)
    return (mr.specified_user_id, role, extra_perms, notes, ac_exclusion,
            no_expand)

  def RemoveRole(self, cnxn, project, member_id):
    """Remove the given member from the project."""
    (owner_ids, committer_ids,
     contributor_ids) = project_helpers.MembersWithoutGivenIDs(
         project, {member_id})
    self.services.project.UpdateProjectRoles(
        cnxn, project.project_id, owner_ids, committer_ids, contributor_ids)

  def UpdateRole(self, cnxn, project, role, member_id):
    """If the user's role was changed, update that in the Project."""
    if not role:
      return  # Role was not in the form data

    if role == framework_helpers.GetRoleName({member_id}, project).lower():
      return  # No change needed

    (owner_ids, committer_ids,
     contributor_ids) = project_helpers.MembersWithGivenIDs(
         project, {member_id}, role)

    self.services.project.UpdateProjectRoles(
        cnxn, project.project_id, owner_ids, committer_ids, contributor_ids)

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

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