# 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

"""Classes to implement the hotlistpeople page and related forms."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

import ezt

from features import hotlist_helpers
from features import hotlist_views
from framework import framework_helpers
from framework import flaskservlet
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

MEMBERS_PER_PAGE = 50


class HotlistPeopleList(servlet.Servlet):
  _PAGE_TEMPLATE = 'project/people-list-page.ezt'
  # Note: using the project's peoplelist page template. minor edits were
  # to make it compatible with HotlistPeopleList
  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.HOTLIST_TAB_PEOPLE

  def AssertBasePermission(self, mr):
    super(HotlistPeopleList, self).AssertBasePermission(mr)
    if not permissions.CanViewHotlist(
        mr.auth.effective_ids, mr.perms, mr.hotlist):
      raise permissions.PermissionException(
          'User is now allowed to view the hotlist people list')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    if mr.auth.user_id:
      self.services.user.AddVisitedHotlist(
          mr.cnxn, mr.auth.user_id, mr.hotlist_id)

    all_members = (mr.hotlist.owner_ids +
                   mr.hotlist.editor_ids + mr.hotlist.follower_ids)

    hotlist_url = hotlist_helpers.GetURLOfHotlist(
        mr.cnxn, mr.hotlist, self.services.user)

    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)

    untrusted_user_group_proxies = []
    # TODO(jojwang): implement FindUntrustedGroups()

    with mr.profiler.Phase('making member views'):
      owner_views = self._MakeMemberViews(mr, mr.hotlist.owner_ids, users_by_id)
      editor_views = self._MakeMemberViews(mr, mr.hotlist.editor_ids,
                                           users_by_id)
      follower_views = self._MakeMemberViews(mr, mr.hotlist.follower_ids,
                                             users_by_id)
      all_member_views = owner_views + editor_views + follower_views

    url_params = [(name, mr.GetParam(name)) for name in
                  framework_helpers.RECOGNIZED_PARAMS]
    # We are passing in None for the project_name because we are not operating
    # under any project.
    pagination = paginate.ArtifactPagination(
        all_member_views, mr.GetPositiveIntParam('num', MEMBERS_PER_PAGE),
        mr.GetPositiveIntParam('start'), None,
        '%s%s' % (hotlist_url, urls.HOTLIST_PEOPLE), url_params=url_params)

    offer_membership_editing = permissions.CanAdministerHotlist(
        mr.auth.effective_ids, mr.perms, mr.hotlist)

    offer_remove_self = (
        not offer_membership_editing and
        mr.auth.user_id and
        mr.auth.user_id in mr.hotlist.editor_ids)

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

    return {
        'is_hotlist': ezt.boolean(True),
        'untrusted_user_groups': untrusted_user_group_proxies,
        'pagination': pagination,
        'initial_add_members': '',
        'subtab_mode': None,
        'initially_expand_form': ezt.boolean(False),
        'newly_added_views': newly_added_views,
        'offer_membership_editing': ezt.boolean(offer_membership_editing),
        'offer_remove_self': ezt.boolean(offer_remove_self),
        'total_num_owners': len(mr.hotlist.owner_ids),
        'check_abandonment': ezt.boolean(True),
        'initial_new_owner_username': '',
        'placeholder': 'new-owner-username',
        'open_dialog': ezt.boolean(False),
        'viewing_user_page': ezt.boolean(True),
        'new_ui_url': '%s/%s/people' % (urls.HOTLISTS, mr.hotlist_id),
    }

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    permit_edit = permissions.CanAdministerHotlist(
        mr.auth.effective_ids, mr.perms, mr.hotlist)
    can_remove_self = (
        not permit_edit and
        mr.auth.user_id and
        mr.auth.user_id in mr.hotlist.editor_ids)
    if not can_remove_self and not permit_edit:
      raise permissions.PermissionException(
          'User is not permitted to edit hotlist membership')
    hotlist_url = hotlist_helpers.GetURLOfHotlist(
        mr.cnxn, mr.hotlist, self.services.user)
    if permit_edit:
      if 'addbtn' in post_data:
        return self.ProcessAddMembers(mr, post_data, hotlist_url)
      elif 'removebtn' in post_data:
        return self.ProcessRemoveMembers(mr, post_data, hotlist_url)
      elif 'changeowners' in post_data:
        return self.ProcessChangeOwnership(mr, post_data)
    if can_remove_self:
      if 'removeself' in post_data:
        return self.ProcessRemoveSelf(mr, hotlist_url)

  def _MakeMemberViews(self, mr, member_ids, users_by_id):
    """Return a sorted list of MemberViews for display by EZT."""
    member_views = [hotlist_views.MemberView(
        mr.auth.user_id, member_id, users_by_id[member_id],
        mr.hotlist) for member_id in member_ids]
    member_views.sort(key=lambda mv: mv.user.email)
    return member_views

  def ProcessChangeOwnership(self, mr, post_data):
    new_owner_id_set = project_helpers.ParseUsernames(
        mr.cnxn, self.services.user, post_data.get('changeowners'))
    remain_as_editor = post_data.get('becomeeditor') == 'on'
    if len(new_owner_id_set) != 1:
      mr.errors.transfer_ownership = (
          'Please add one valid user email.')
    else:
      new_owner_id = new_owner_id_set.pop()
      if self.services.features.LookupHotlistIDs(
          mr.cnxn, [mr.hotlist.name], [new_owner_id]):
        mr.errors.transfer_ownership = (
            'This user already owns a hotlist with the same name')

    if mr.errors.AnyErrors():
      self.PleaseCorrect(
          mr, initial_new_owner_username=post_data.get('changeowners'),
          open_dialog=ezt.boolean(True))
    else:
      old_and_new_owner_ids = [new_owner_id] + mr.hotlist.owner_ids
      (_, editor_ids, follower_ids) = hotlist_helpers.MembersWithoutGivenIDs(
          mr.hotlist, old_and_new_owner_ids)
      if remain_as_editor and mr.hotlist.owner_ids:
        editor_ids.append(mr.hotlist.owner_ids[0])

      self.services.features.UpdateHotlistRoles(
          mr.cnxn, mr.hotlist_id, [new_owner_id], editor_ids, follower_ids)

      hotlist = self.services.features.GetHotlist(mr.cnxn, mr.hotlist_id)
      hotlist_url = hotlist_helpers.GetURLOfHotlist(
        mr.cnxn, hotlist, self.services.user)
      return framework_helpers.FormatAbsoluteURL(
          mr,'%s%s' % (hotlist_url, urls.HOTLIST_PEOPLE),
          saved=1, ts=int(time.time()),
          include_project=False)

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

    Args:
      mr: common information parsed from the HTTP request.
      post_data: dictionary of form data
      hotlist_url: hotlist_url to return to after data has been processed.

    Returns:
      String URL to redirect the user to after processing
    """
    # NOTE: using project_helpers function
    new_member_ids = project_helpers.ParseUsernames(
        mr.cnxn, self.services.user, post_data.get('addmembers'))
    if not new_member_ids or not post_data.get('addmembers'):
      mr.errors.incorrect_email_input = (
          'Please give full emails seperated by commas.')
    role = post_data['role']

    (owner_ids, editor_ids, follower_ids) = hotlist_helpers.MembersWithGivenIDs(
        mr.hotlist, new_member_ids, role)
    # TODO(jojwang): implement MAX_HOTLIST_PEOPLE

    if not owner_ids:
      mr.errors.addmembers = (
          'Cannot have a hotlist without an owner; please leave at least one.')

    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:
      self.services.features.UpdateHotlistRoles(
          mr.cnxn, mr.hotlist_id, owner_ids, editor_ids, follower_ids)
      return framework_helpers.FormatAbsoluteURL(
          mr, '%s%s' % (
              hotlist_url, urls.HOTLIST_PEOPLE),
          saved=1, ts=int(time.time()),
          new=','.join([str(u) for u in new_member_ids]),
          include_project=False)

  def ProcessRemoveMembers(self, mr, post_data, hotlist_url):
    """Process the user's request to remove members."""
    #TODO: convert for flask
    #remove_strs = post_data.getlist('remove')
    remove_strs = post_data.getall('remove')
    logging.info('remove_strs = %r', remove_strs)
    remove_ids = set(
        self.services.user.LookupUserIDs(mr.cnxn, remove_strs).values())
    (owner_ids, editor_ids,
     follower_ids) = hotlist_helpers.MembersWithoutGivenIDs(
         mr.hotlist, remove_ids)

    self.services.features.UpdateHotlistRoles(
        mr.cnxn, mr.hotlist_id, owner_ids, editor_ids, follower_ids)

    return framework_helpers.FormatAbsoluteURL(
        mr, '%s%s' % (
              hotlist_url, urls.HOTLIST_PEOPLE),
          saved=1, ts=int(time.time()), include_project=False)

  def ProcessRemoveSelf(self, mr, hotlist_url):
    """Process the request to remove the logged-in user."""
    remove_ids = [mr.auth.user_id]

    # This function does no permission checking; that's done by the caller.
    (owner_ids, editor_ids,
        follower_ids) = hotlist_helpers.MembersWithoutGivenIDs(
            mr.hotlist, remove_ids)

    self.services.features.UpdateHotlistRoles(
        mr.cnxn, mr.hotlist_id, owner_ids, editor_ids, follower_ids)

    return framework_helpers.FormatAbsoluteURL(
        mr, '%s%s' % (
              hotlist_url, urls.HOTLIST_PEOPLE),
          saved=1, ts=int(time.time()), include_project=False)

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

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