# 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 user group admin page."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from framework import flaskservlet
from framework import framework_helpers
from framework import permissions
from framework import servlet
from framework import urls
from proto import usergroup_pb2
from services import usergroup_svc
from sitewide import group_helpers


class GroupAdmin(flaskservlet.FlaskServlet):
  """The group admin page."""

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

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

    _, 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]
    if not permissions.CanEditGroup(
        mr.perms, mr.auth.effective_ids, owner_ids):
      raise permissions.PermissionException(
          'User is not allowed to edit 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)
    visibility_levels = group_helpers.BuildUserGroupVisibilityOptions()
    initial_visibility = group_helpers.GroupVisibilityView(
        group_settings.who_can_view_members)
    group_types = group_helpers.BuildUserGroupTypeOptions()
    import_group = bool(group_settings.ext_group_type)
    if import_group:
      initial_group_type = group_helpers.GroupTypeView(
          group_settings.ext_group_type)
    else:
      initial_group_type = ''

    if group_settings.friend_projects:
      initial_friendprojects = ', '.join(
          list(self.services.project.LookupProjectNames(
              mr.cnxn, group_settings.friend_projects).values()))
    else:
      initial_friendprojects = ''

    return {
        'admin_tab_mode': 'st2',
        'groupadmin': True,
        'groupid': group_id,
        'groupname': mr.viewed_username,
        'group_types': group_types,
        'import_group': import_group or '',
        'initial_friendprojects': initial_friendprojects,
        'initial_group_type': initial_group_type,
        'initial_visibility': initial_visibility,
        'offer_membership_editing': True,
        'visibility_levels': visibility_levels,
        }

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    # 1. Gather data from the request.
    group_name = mr.viewed_username
    group_id = mr.viewed_user_auth.user_id

    if post_data.get('import_group'):
      vis_level = usergroup_pb2.MemberVisibility.OWNERS
      ext_group_type = post_data.get('group_type')
      friend_projects = ''
      if not ext_group_type:
        mr.errors.groupimport = 'Please provide external group type'
      else:
        ext_group_type = usergroup_pb2.GroupType(int(ext_group_type))
    else:
      vis_level = post_data.get('visibility')
      ext_group_type = None
      friend_projects = post_data.get('friendprojects', '')
      if vis_level:
        vis_level = usergroup_pb2.MemberVisibility(int(vis_level))
      else:
        mr.errors.groupimport = 'Cannot update settings for imported group'

    if not mr.errors.AnyErrors():
      project_ids, error = self.services.usergroup.ValidateFriendProjects(
          mr.cnxn, self.services, friend_projects)
      if error:
        mr.errors.friendprojects = error

    # 2. Call services layer to save changes.
    if not mr.errors.AnyErrors():
      group_settings = usergroup_pb2.UserGroupSettings(
        who_can_view_members=vis_level,
        ext_group_type=ext_group_type,
        friend_projects=project_ids)
      self.services.usergroup.UpdateSettings(
          mr.cnxn, group_id, group_settings)

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

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

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