# 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

"""Servlet for creating new hotlists."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time
import re

from features import hotlist_helpers
from framework import exceptions
from framework import flaskservlet
from framework import framework_bizobj
from framework import framework_helpers
from framework import permissions
from framework import servlet
from services import features_svc


_MSG_HOTLIST_NAME_NOT_AVAIL = 'You already have a hotlist with that name.'
_MSG_MISSING_HOTLIST_NAME = 'Missing hotlist name'
_MSG_INVALID_HOTLIST_NAME = 'Invalid hotlist name'
_MSG_MISSING_HOTLIST_SUMMARY = 'Missing hotlist summary'
_MSG_INVALID_ISSUES_INPUT = 'Issues input is invalid'
_MSG_INVALID_MEMBERS_INPUT = 'One or more editor emails is not valid.'


class HotlistCreate(flaskservlet.FlaskServlet):
  """HotlistCreate shows a simple page with a form to create a hotlist."""

  _PAGE_TEMPLATE = 'features/hotlist-create-page.ezt'

  def AssertBasePermission(self, mr):
    """Check whether the user has any permission to visit this page.

    Args:
      mr: commonly used info parsed from the request.
    """
    super(HotlistCreate, self).AssertBasePermission(mr)
    if not permissions.CanCreateHotlist(mr.perms):
      raise permissions.PermissionException(
          'User is not allowed to create a hotlist.')

  def GatherPageData(self, mr):
    return {
        'user_tab_mode': 'st6',
        'initial_name': '',
        'initial_summary': '',
        'initial_description': '',
        'initial_editors': '',
        'initial_privacy': 'no',
        }

  def ProcessFormData(self, mr, post_data):
    """Process the hotlist create form.

    Args:
      mr: commonly used info parsed from the request.
      post_data: The post_data dict for the current request.

    Returns:
      String URL to redirect the user to after processing.
    """
    hotlist_name = post_data.get('hotlistname')
    if not hotlist_name:
      mr.errors.hotlistname = _MSG_MISSING_HOTLIST_NAME
    elif not framework_bizobj.IsValidHotlistName(hotlist_name):
      mr.errors.hotlistname = _MSG_INVALID_HOTLIST_NAME

    summary = post_data.get('summary')
    if not summary:
      mr.errors.summary = _MSG_MISSING_HOTLIST_SUMMARY

    description = post_data.get('description', '')

    editors = post_data.get('editors', '')
    editor_ids = []
    if editors:
      editor_emails = [
          email.strip() for email in editors.split(',')]
      try:
        editor_dict = self.services.user.LookupUserIDs(mr.cnxn, editor_emails)
        editor_ids = list(editor_dict.values())
      except exceptions.NoSuchUserException:
        mr.errors.editors = _MSG_INVALID_MEMBERS_INPUT
      # In case the logged-in user specifies themselves as an editor, ignore it.
      editor_ids = [eid for eid in editor_ids if eid != mr.auth.user_id]

    is_private = post_data.get('is_private')

    if not mr.errors.AnyErrors():
      try:
        hotlist = self.services.features.CreateHotlist(
            mr.cnxn, hotlist_name, summary, description,
            owner_ids=[mr.auth.user_id], editor_ids=editor_ids,
            is_private=(is_private == 'yes'),
            ts=int(time.time()))
      except features_svc.HotlistAlreadyExists:
        mr.errors.hotlistname = _MSG_HOTLIST_NAME_NOT_AVAIL

    if mr.errors.AnyErrors():
      self.PleaseCorrect(
          mr, initial_name=hotlist_name, initial_summary=summary,
          initial_description=description,
          initial_editors=editors, initial_privacy=is_private)
    else:
      return framework_helpers.FormatAbsoluteURL(
          mr, hotlist_helpers.GetURLOfHotlist(
              mr.cnxn, hotlist, self.services.user),
          include_project=False)

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

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