# 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 a user group, including a paginated list of members."""
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 flaskservlet
from framework import framework_helpers
from framework import framework_views
from framework import paginate
from framework import permissions
from framework import servlet
from project import project_helpers
from proto import usergroup_pb2
from sitewide import group_helpers
from sitewide import sitewide_views

MEMBERS_PER_PAGE = 50


class GroupDetail(servlet.Servlet):
  """The group detail page presents information about one user group."""

  _PAGE_TEMPLATE = 'sitewide/group-detail-page.ezt'

  def AssertBasePermission(self, mr):
    """Assert that the user has the permissions needed to view this page."""
    super(GroupDetail, self).AssertBasePermission(mr)

    group_id = mr.viewed_user_auth.user_id
    group_settings = self.services.usergroup.GetGroupSettings(
        mr.cnxn, group_id)
    if not group_settings:
      return

    member_ids, owner_ids = self.services.usergroup.LookupAllMembers(
          mr.cnxn, [group_id])
    (owned_project_ids, membered_project_ids,
     contrib_project_ids) = self.services.project.GetUserRolesInAllProjects(
         mr.cnxn, mr.auth.effective_ids)
    project_ids = owned_project_ids.union(
        membered_project_ids).union(contrib_project_ids)
    if not permissions.CanViewGroupMembers(
        mr.perms, mr.auth.effective_ids, group_settings, member_ids[group_id],
        owner_ids[group_id], project_ids):
      raise permissions.PermissionException(
          'User is not allowed to view a user group')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    group_id = mr.viewed_user_auth.user_id
    group_settings = self.services.usergroup.GetGroupSettings(
        mr.cnxn, group_id)
    if not group_settings:
      raise exceptions.NoSuchGroupException()

    member_ids_dict, owner_ids_dict = (
        self.services.usergroup.LookupVisibleMembers(
            mr.cnxn, [group_id], mr.perms, mr.auth.effective_ids,
            self.services))
    member_ids = member_ids_dict[group_id]
    owner_ids = owner_ids_dict[group_id]
    member_pbs_dict = self.services.user.GetUsersByIDs(
        mr.cnxn, member_ids)
    owner_pbs_dict = self.services.user.GetUsersByIDs(
        mr.cnxn, owner_ids)
    member_dict = {}
    for user_id, user_pb in member_pbs_dict.items():
      member_view = group_helpers.GroupMemberView(user_pb, group_id, 'member')
      member_dict[user_id] = member_view
    owner_dict = {}
    for user_id, user_pb in owner_pbs_dict.items():
      member_view = group_helpers.GroupMemberView(user_pb, group_id, 'owner')
      owner_dict[user_id] = member_view

    member_user_views = []
    member_user_views.extend(
        sorted(list(owner_dict.values()), key=lambda u: u.email))
    member_user_views.extend(
        sorted(list(member_dict.values()), key=lambda u: u.email))

    group_view = sitewide_views.GroupView(
        mr.viewed_user_auth.email, len(member_ids), group_settings,
        mr.viewed_user_auth.user_id)
    url_params = [(name, mr.GetParam(name)) for name in
                  framework_helpers.RECOGNIZED_PARAMS]
    pagination = paginate.ArtifactPagination(
        member_user_views, mr.GetPositiveIntParam('num', MEMBERS_PER_PAGE),
        mr.GetPositiveIntParam('start'), mr.project_name, group_view.detail_url,
        url_params=url_params)

    is_imported_group = bool(group_settings.ext_group_type)

    offer_membership_editing = permissions.CanEditGroup(
        mr.perms, mr.auth.effective_ids, owner_ids) and not is_imported_group

    group_type = 'Monorail user group'
    if group_settings.ext_group_type:
      group_type = str(group_settings.ext_group_type).capitalize()

    return {
        'admin_tab_mode': self.ADMIN_TAB_META,
        'offer_membership_editing': ezt.boolean(offer_membership_editing),
        'initial_add_members': '',
        'initially_expand_form': ezt.boolean(False),
        'groupid': group_id,
        'groupname': mr.viewed_username,
        'settings': group_settings,
        'group_type': group_type,
        'pagination': pagination,
        }

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    _, owner_ids_dict = self.services.usergroup.LookupMembers(
        mr.cnxn, [mr.viewed_user_auth.user_id])
    owner_ids = owner_ids_dict[mr.viewed_user_auth.user_id]
    permit_edit = permissions.CanEditGroup(
        mr.perms, mr.auth.effective_ids, owner_ids)
    if not permit_edit:
      raise permissions.PermissionException(
          'User is not permitted to edit group membership')

    group_settings = self.services.usergroup.GetGroupSettings(
        mr.cnxn, mr.viewed_user_auth.user_id)
    if bool(group_settings.ext_group_type):
      raise permissions.PermissionException(
          'Imported groups are read-only')

    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. Gather data from the request.
    group_id = mr.viewed_user_auth.user_id
    add_members_str = post_data.get('addmembers')
    new_member_ids = project_helpers.ParseUsernames(
        mr.cnxn, self.services.user, add_members_str)
    role = post_data['role']

    # 2. Call services layer to save changes.
    if not mr.errors.AnyErrors():
      try:
        self.services.usergroup.UpdateMembers(
            mr.cnxn, group_id, new_member_ids, role)
      except exceptions.CircularGroupException:
        mr.errors.addmembers = (
            'The members are already ancestors of current group.')

    # 3. Determine the next page in the UI flow.
    if mr.errors.AnyErrors():
      self.PleaseCorrect(
          mr, initial_add_members=add_members_str,
          initially_expand_form=ezt.boolean(True))
    else:
      return framework_helpers.FormatAbsoluteURL(
          mr, '/g/%s/' % mr.viewed_username, include_project=False,
          saved=1, ts=int(time.time()))

  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. Gather data from the request.
    remove_strs = post_data.getall('remove')
    # TODO(crbug.com/monorail/10936): getall in Flask is getlist
    # remove_strs = post_data.getlist('remove')
    logging.info('remove_strs = %r', remove_strs)

    if not remove_strs:
      mr.errors.remove = 'No users specified'

    # 2. Call services layer to save changes.
    if not mr.errors.AnyErrors():
      remove_ids = set(
          self.services.user.LookupUserIDs(mr.cnxn, remove_strs).values())
      self.services.usergroup.RemoveMembers(
          mr.cnxn, mr.viewed_user_auth.user_id, remove_ids)

    # 3. Determine the next page in the UI flow.
    if mr.errors.AnyErrors():
      self.PleaseCorrect(mr)
    else:
      return framework_helpers.FormatAbsoluteURL(
          mr, '/g/%s/' % mr.viewed_username, include_project=False,
          saved=1, ts=int(time.time()))

  # def GetGroupDetail(self, **kwargs):
  #   return self.handler(**kwargs)

  # def PostGroupDetail(self, **kwargs):
  #   return self.handler(**kwargs)
