# Copyright 2018 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

"""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 collections
import logging
import time

import ezt

from framework import authdata
from framework import flaskservlet
from framework import framework_bizobj
from framework import framework_helpers
from framework import servlet
from framework import urls
from framework import permissions
from tracker import field_helpers
from tracker import template_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers
from tracker import tracker_views
from services import user_svc
from proto import tracker_pb2


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

  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_PROCESS
  _PAGE_TEMPLATE = 'tracker/template-detail-page.ezt'
  _PROCESS_SUBTAB = flaskservlet.FlaskServlet.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 self.CheckPerm(mr, permissions.EDIT_PROJECT):
      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 is not "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 is "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 is not '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 is '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)
