# 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.

"""Classes for the user profile page ("my page")."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import time
import json

import ezt

import settings
from businesslogic import work_env
from framework import framework_helpers
from framework import framework_views
from framework import permissions
from framework import servlet
from framework import timestr
from framework import xsrf
from project import project_views


class UserProfile(servlet.Servlet):
  """Shows a page of information about a user."""

  _PAGE_TEMPLATE = 'sitewide/user-profile-page.ezt'

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page."""
    viewed_user = mr.viewed_user_auth.user_pb
    if self.services.usergroup.GetGroupSettings(
        mr.cnxn, mr.viewed_user_auth.user_id):
      url = framework_helpers.FormatAbsoluteURL(
          mr, '/g/%s/' % viewed_user.email, include_project=False)
      self.redirect(url, abort=True)  # Show group page instead.

    with work_env.WorkEnv(mr, self.services) as we:
      project_lists = we.GetUserProjects(mr.viewed_user_auth.effective_ids)

      (visible_ownership, visible_archived, visible_membership,
       visible_contrib) = project_lists

    with mr.profiler.Phase('Getting user groups'):
      group_settings = self.services.usergroup.GetAllGroupSettings(
          mr.cnxn, mr.viewed_user_auth.effective_ids)
      member_ids, owner_ids = self.services.usergroup.LookupAllMembers(
          mr.cnxn, list(group_settings.keys()))
      friend_project_ids = [] # TODO(issue 4202): implement this.
      visible_group_ids = []
      for group_id in group_settings:
        if permissions.CanViewGroupMembers(
            mr.perms, mr.auth.effective_ids, group_settings[group_id],
            member_ids[group_id], owner_ids[group_id], friend_project_ids):
          visible_group_ids.append(group_id)

      user_group_views = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, visible_group_ids)
      user_group_views = sorted(
          list(user_group_views.values()), key=lambda ugv: ugv.email)

    with mr.profiler.Phase('Getting linked accounts'):
      linked_parent = None
      linked_children = []
      linked_views = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user,
          [viewed_user.linked_parent_id],
          viewed_user.linked_child_ids)
      if viewed_user.linked_parent_id:
        linked_parent = linked_views[viewed_user.linked_parent_id]
      if viewed_user.linked_child_ids:
        linked_children = [
          linked_views[child_id] for child_id in viewed_user.linked_child_ids]
      offer_unlink = (mr.auth.user_id == viewed_user.user_id or
                      mr.auth.user_id in linked_views)

    incoming_invite_users = []
    outgoing_invite_users = []
    possible_parent_accounts = []
    can_edit_invites = mr.auth.user_id == mr.viewed_user_auth.user_id
    display_link_invites = can_edit_invites or mr.auth.user_pb.is_site_admin
    # TODO(jrobbins): allow site admin to edit invites for other users.
    if display_link_invites:
      with work_env.WorkEnv(mr, self.services, phase='Getting link invites'):
        incoming_invite_ids, outgoing_invite_ids = we.GetPendingLinkedInvites(
            user_id=viewed_user.user_id)
        invite_views = framework_views.MakeAllUserViews(
          mr.cnxn, self.services.user, incoming_invite_ids, outgoing_invite_ids)
        incoming_invite_users = [
            invite_views[uid] for uid in incoming_invite_ids]
        outgoing_invite_users = [
            invite_views[uid] for uid in outgoing_invite_ids]
        possible_parent_accounts = _ComputePossibleParentAccounts(
            we, mr.viewed_user_auth.user_view, linked_parent, linked_children)

    viewed_user_display_name = framework_views.GetViewedUserDisplayName(mr)

    with work_env.WorkEnv(mr, self.services) as we:
      starred_projects = we.ListStarredProjects(
          viewed_user_id=mr.viewed_user_auth.user_id)
      logged_in_starred = we.ListStarredProjects()
      logged_in_starred_pids = {p.project_id for p in logged_in_starred}

    starred_user_ids = self.services.user_star.LookupStarredItemIDs(
        mr.cnxn, mr.viewed_user_auth.user_id)
    starred_user_dict = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user, starred_user_ids)
    starred_users = list(starred_user_dict.values())
    starred_users_json = json.dumps(
      [uv.display_name for uv in starred_users])

    is_user_starred = self._IsUserStarred(
        mr.cnxn, mr.auth.user_id, mr.viewed_user_auth.user_id)

    if viewed_user.last_visit_timestamp:
      last_visit_str = timestr.FormatRelativeDate(
          viewed_user.last_visit_timestamp, days_only=True)
      last_visit_str = last_visit_str or 'Less than 2 days ago'
    else:
      last_visit_str = 'Never'

    if viewed_user.email_bounce_timestamp:
      last_bounce_str = timestr.FormatRelativeDate(
          viewed_user.email_bounce_timestamp, days_only=True)
      last_bounce_str = last_bounce_str or 'Less than 2 days ago'
    else:
      last_bounce_str = None

    can_ban = permissions.CanBan(mr, self.services)
    viewed_user_is_spammer = viewed_user.banned.lower() == 'spam'
    viewed_user_may_be_spammer = not viewed_user_is_spammer
    all_projects = self.services.project.GetAllProjects(mr.cnxn)
    for project_id in all_projects:
      project = all_projects[project_id]
      viewed_user_perms = permissions.GetPermissions(viewed_user,
          mr.viewed_user_auth.effective_ids, project)
      if (viewed_user_perms != permissions.EMPTY_PERMISSIONSET and
          viewed_user_perms != permissions.USER_PERMISSIONSET):
        viewed_user_may_be_spammer = False

    ban_token = None
    ban_spammer_token = None
    if mr.auth.user_id and can_ban:
      form_token_path = mr.request_path + 'ban.do'
      ban_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path)
      form_token_path = mr.request_path + 'banSpammer.do'
      ban_spammer_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path)

    can_delete_user = permissions.CanExpungeUsers(mr)

    page_data = {
        'user_tab_mode': 'st2',
        'viewed_user_display_name': viewed_user_display_name,
        'viewed_user_may_be_spammer': ezt.boolean(viewed_user_may_be_spammer),
        'viewed_user_is_spammer': ezt.boolean(viewed_user_is_spammer),
        'viewed_user_is_banned': ezt.boolean(viewed_user.banned),
        'owner_of_projects': [
            project_views.ProjectView(
                p, starred=p.project_id in logged_in_starred_pids)
            for p in visible_ownership],
        'committer_of_projects': [
            project_views.ProjectView(
                p, starred=p.project_id in logged_in_starred_pids)
            for p in visible_membership],
        'contributor_to_projects': [
            project_views.ProjectView(
                p, starred=p.project_id in logged_in_starred_pids)
            for p in visible_contrib],
        'owner_of_archived_projects': [
            project_views.ProjectView(p) for p in visible_archived],
        'starred_projects': [
            project_views.ProjectView(
                p, starred=p.project_id in logged_in_starred_pids)
            for p in starred_projects],
        'starred_users': starred_users,
        'starred_users_json': starred_users_json,
        'is_user_starred': ezt.boolean(is_user_starred),
        'viewing_user_page': ezt.boolean(True),
        'last_visit_str': last_visit_str,
        'last_bounce_str': last_bounce_str,
        'vacation_message': viewed_user.vacation_message,
        'can_ban': ezt.boolean(can_ban),
        'ban_token': ban_token,
        'ban_spammer_token': ban_spammer_token,
        'user_groups': user_group_views,
        'linked_parent': linked_parent,
        'linked_children': linked_children,
        'incoming_invite_users': incoming_invite_users,
        'outgoing_invite_users': outgoing_invite_users,
        'possible_parent_accounts': possible_parent_accounts,
        'can_edit_invites': ezt.boolean(can_edit_invites),
        'offer_unlink': ezt.boolean(offer_unlink),
        'can_delete_user': ezt.boolean(can_delete_user),
        }

    viewed_user_prefs = None
    if mr.perms.HasPerm(permissions.EDIT_OTHER_USERS, None, None):
      with work_env.WorkEnv(mr, self.services) as we:
        viewed_user_prefs = we.GetUserPrefs(mr.viewed_user_auth.user_id)

    user_settings = (
        framework_helpers.UserSettings.GatherUnifiedSettingsPageData(
        mr.auth.user_id, mr.viewed_user_auth.user_view, viewed_user,
        viewed_user_prefs))
    page_data.update(user_settings)

    return page_data

  def _IsUserStarred(self, cnxn, logged_in_user_id, viewed_user_id):
    """Return whether the logged in user starred the viewed user."""
    if logged_in_user_id:
      return self.services.user_star.IsItemStarredBy(
          cnxn, viewed_user_id, logged_in_user_id)
    return False

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    has_admin_perm = mr.perms.HasPerm(permissions.EDIT_OTHER_USERS, None, None)
    with work_env.WorkEnv(mr, self.services) as we:
      framework_helpers.UserSettings.ProcessSettingsForm(
          we, post_data, mr.viewed_user_auth.user_pb, admin=has_admin_perm)

    # TODO(jrobbins): Check all calls to FormatAbsoluteURL for include_project.
    return framework_helpers.FormatAbsoluteURL(
        mr, mr.viewed_user_auth.user_view.profile_url, include_project=False,
        saved=1, ts=int(time.time()))

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

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


def _ComputePossibleParentAccounts(
    we, user_view, linked_parent, linked_children):
  """Return a list of email addresses of possible parent accounts."""
  if not user_view:
    return []  # Anon user cannot link to any account.
  if linked_parent or linked_children:
    return []  # If account is already linked in any way, don't offer.
  possible_domains = settings.linkable_domains.get(user_view.domain, [])
  possible_emails = ['%s@%s' % (user_view.username, domain)
                     for domain in possible_domains]
  found_users, _ = we.ListReferencedUsers(possible_emails)
  found_emails = [user.email for user in found_users]
  return found_emails


class BanUser(servlet.Servlet):
  """Bans or un-bans a user."""

  def ProcessFormData(self, mr, post_data):
    """Process the posted form."""
    if not permissions.CanBan(mr, self.services):
      raise permissions.PermissionException(
          "You do not have permission to ban users.")

    framework_helpers.UserSettings.ProcessBanForm(
        mr.cnxn, self.services.user, post_data, mr.viewed_user_auth.user_id,
        mr.viewed_user_auth.user_pb)

    # TODO(jrobbins): Check all calls to FormatAbsoluteURL for include_project.
    return framework_helpers.FormatAbsoluteURL(
        mr, mr.viewed_user_auth.user_view.profile_url, include_project=False,
        saved=1, ts=int(time.time()))

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