# 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

"""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 jsonfeed
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,
    permissions.MODERATE_SPAM,
    ]


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.getall('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)
