# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A servlet for project owners to create a new template"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import time

import ezt

from framework import framework_helpers
from framework import permissions
from framework import servlet
from framework import urls
from tracker import field_helpers
from tracker import template_helpers
from tracker import tracker_views
from mrproto import tracker_pb2


class TemplateCreate(servlet.Servlet):
  """Servlet allowing project owners to create an issue template."""

  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PROCESS
  _PAGE_TEMPLATE = 'tracker/template-detail-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_TEMPLATES

  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(TemplateCreate, self).AssertBasePermission(mr)
    if not permissions.CanEditProjectConfig(mr, self.services):
      raise permissions.PermissionException(
          'User is not allowed to administer this project')

  def GatherPageData(self, mr):
    """Build up a dictionary of data values to use when rendering the page.

    Args:
      mr: commonly used info parsed from the request.

    Returns:
      Dict of values used by EZT for rendering the page.
    """

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    field_views = tracker_views.MakeAllFieldValueViews(
        config, [], [], [], {})
    approval_subfields_present = any(
        fv.field_def.is_approval_subfield for fv in field_views)

    initial_phases = [tracker_pb2.Phase()] * template_helpers.MAX_NUM_PHASES
    return {
        'admin_tab_mode':
            self._PROCESS_SUBTAB,
        'allow_edit':
            ezt.boolean(True),
        'uneditable_fields':
            ezt.boolean(False),
        'new_template_form':
            ezt.boolean(True),
        'initial_members_only':
            ezt.boolean(False),
        'template_name':
            '',
        'initial_content':
            '',
        'initial_must_edit_summary':
            ezt.boolean(False),
        'initial_summary':
            '',
        'initial_status':
            '',
        'initial_owner':
            '',
        'initial_owner_defaults_to_member':
            ezt.boolean(False),
        'initial_components':
            '',
        'initial_component_required':
            ezt.boolean(False),
        'initial_admins':
            '',
        'fields':
            [
                view for view in field_views
                if view.field_def.type_name != "APPROVAL_TYPE"
            ],
        'initial_add_approvals':
            ezt.boolean(False),
        'initial_phases':
            initial_phases,
        'approvals':
            [
                view for view in field_views
                if view.field_def.type_name == "APPROVAL_TYPE"
            ],
        'prechecked_approvals': [],
        'required_approval_ids': [],
        'approval_subfields_present':
            ezt.boolean(approval_subfields_present),
        # We do not support setting phase field values during template creation.
        'phase_fields_present':
            ezt.boolean(False),
    }

  def ProcessFormData(self, mr, post_data):
    """Validate and store the contents of the issues tracker admin page.

    Args:
      mr: commonly used info parsed from the request.
      post_data: HTML form data from the request.

    Returns:
      String URL to redirect the user to, or None if response was already sent.
    """

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    parsed = template_helpers.ParseTemplateRequest(post_data, config)
    field_helpers.ShiftEnumFieldsIntoLabels(
        parsed.labels, [], parsed.field_val_strs, [], config)

    if not parsed.name:
      mr.errors.name = 'Please provide a template name'
    if self.services.template.GetTemplateByName(mr.cnxn, parsed.name,
                                                mr.project_id):
      mr.errors.name = 'Template with name %s already exists' % parsed.name

    (admin_ids, owner_id, component_ids,
     field_values, phases,
     approvals) = template_helpers.GetTemplateInfoFromParsed(
         mr, self.services, parsed, config)

    labels = [label for label in parsed.labels if label]
    field_helpers.AssertCustomFieldsEditPerms(
        mr, config, field_values, [], [], labels, [])

    if mr.errors.AnyErrors():
      field_views = tracker_views.MakeAllFieldValueViews(
          config, [], [], field_values, {})
      prechecked_approvals = template_helpers.GetCheckedApprovalsFromParsed(
          parsed.approvals_to_phase_idx)

      self.PleaseCorrect(
          mr,
          initial_members_only=ezt.boolean(parsed.members_only),
          template_name=parsed.name,
          initial_content=parsed.summary,
          initial_must_edit_summary=ezt.boolean(parsed.summary_must_be_edited),
          initial_description=parsed.content,
          initial_status=parsed.status,
          initial_owner=parsed.owner_str,
          initial_owner_defaults_to_member=ezt.boolean(
              parsed.owner_defaults_to_member),
          initial_components=', '.join(parsed.component_paths),
          initial_component_required=ezt.boolean(parsed.component_required),
          initial_admins=parsed.admin_str,
          labels=parsed.labels,
          fields=[view for view in field_views
                  if view.field_def.type_name != 'APPROVAL_TYPE'],
          initial_add_approvals=ezt.boolean(parsed.add_approvals),
          initial_phases=[tracker_pb2.Phase(name=name) for name in
                          parsed.phase_names],
          approvals=[view for view in field_views
                     if view.field_def.type_name == 'APPROVAL_TYPE'],
          prechecked_approvals=prechecked_approvals,
          required_approval_ids=parsed.required_approval_ids
      )
      return

    self.services.template.CreateIssueTemplateDef(
        mr.cnxn, mr.project_id, parsed.name, parsed.content, parsed.summary,
        parsed.summary_must_be_edited, parsed.status, parsed.members_only,
        parsed.owner_defaults_to_member, parsed.component_required,
        owner_id, labels, component_ids, admin_ids, field_values, phases=phases,
        approval_values=approvals)

    return framework_helpers.FormatAbsoluteURL(
        mr, urls.ADMIN_TEMPLATES, saved=1, ts=int(time.time()))

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

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