# 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(servlet.Servlet):
  """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)
