# 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 that implements the entry of new issues."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import difflib
import logging
import string
import time

from businesslogic import work_env
from features import hotlist_helpers
from features import send_notifications
from framework import exceptions
from framework import flaskservlet
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import permissions
from framework import servlet
from framework import template_helpers
from framework import urls
import ezt
from tracker import field_helpers
from tracker import template_helpers as issue_tmpl_helpers
from tracker import tracker_bizobj
from tracker import tracker_constants
from tracker import tracker_helpers
from tracker import tracker_views
from proto import tracker_pb2

PLACEHOLDER_SUMMARY = 'Enter one-line summary'
PHASES_WITH_MILESTONES = ['Beta', 'Stable', 'Stable-Exp', 'Stable-Full']
CORP_RESTRICTION_LABEL = 'Restrict-View-Google'
RESTRICTED_FLT_FIELDS = ['notice', 'whitepaper', 'm-approved']


class IssueEntry(servlet.Servlet):
  """IssueEntry shows a page with a simple form to enter a new issue."""

  _PAGE_TEMPLATE = 'tracker/issue-entry-page.ezt'
  _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_ISSUES

  # The issue filing wizard is a separate app that posted back to Monorail's
  # issue entry page. To make this possible for the wizard, we need to allow
  # XHR-scoped XSRF tokens.
  ALLOW_XHR = True

  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(IssueEntry, self).AssertBasePermission(mr)
    if not self.CheckPerm(mr, permissions.CREATE_ISSUE):
      raise permissions.PermissionException(
          'User is not allowed to enter an issue')

  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.
    """
    with mr.profiler.Phase('getting config'):
      config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    # In addition to checking perms, we adjust some default field values for
    # project members.
    is_member = framework_bizobj.UserIsInProject(
        mr.project, mr.auth.effective_ids)
    page_perms = self.MakePagePerms(
        mr, None,
        permissions.CREATE_ISSUE,
        permissions.SET_STAR,
        permissions.EDIT_ISSUE,
        permissions.EDIT_ISSUE_SUMMARY,
        permissions.EDIT_ISSUE_STATUS,
        permissions.EDIT_ISSUE_OWNER,
        permissions.EDIT_ISSUE_CC)


    with work_env.WorkEnv(mr, self.services) as we:
      userprefs = we.GetUserPrefs(mr.auth.user_id)
      code_font = any(pref for pref in userprefs.prefs
                      if pref.name == 'code_font' and pref.value == 'true')

    template = self._GetTemplate(mr.cnxn, config, mr.template_name, is_member)

    if template.summary:
      initial_summary = template.summary
      initial_summary_must_be_edited = template.summary_must_be_edited
    else:
      initial_summary = PLACEHOLDER_SUMMARY
      initial_summary_must_be_edited = True

    if template.status:
      initial_status = template.status
    elif is_member:
      initial_status = 'Accepted'
    else:
      initial_status = 'New'  # not offering meta, only used in hidden field.

    component_paths = []
    for component_id in template.component_ids:
      component_paths.append(
          tracker_bizobj.FindComponentDefByID(component_id, config).path)
    initial_components = ', '.join(component_paths)

    if template.owner_id:
      initial_owner = framework_views.MakeUserView(
          mr.cnxn, self.services.user, template.owner_id)
    elif template.owner_defaults_to_member and page_perms.EditIssue:
      initial_owner = mr.auth.user_view
    else:
      initial_owner = None

    if initial_owner:
      initial_owner_name = initial_owner.email
      owner_avail_state = initial_owner.avail_state
      owner_avail_message_short = initial_owner.avail_message_short
    else:
      initial_owner_name = ''
      owner_avail_state = None
      owner_avail_message_short = None

    # Check whether to allow attachments from the entry page
    allow_attachments = tracker_helpers.IsUnderSoftAttachmentQuota(mr.project)

    config_view = tracker_views.ConfigView(mr, self.services, config, template)
    # If the user followed a link that specified the template name, make sure
    # that it is also in the menu as the current choice.
    # TODO(jeffcarp): Unit test this.
    config_view.template_view.can_view = ezt.boolean(True)

    # TODO(jeffcarp): Unit test this.
    offer_templates = len(config_view.template_names) > 1
    restrict_to_known = config.restrict_to_known
    link_or_template_labels = mr.GetListParam('labels', template.labels)
    labels, _derived_labels = tracker_bizobj.ExplicitAndDerivedNonMaskedLabels(
        link_or_template_labels, [], config)

    # Users with restrict_new_issues user pref automatically add R-V-G.
    with work_env.WorkEnv(mr, self.services) as we:
      userprefs = we.GetUserPrefs(mr.auth.user_id)
      restrict_new_issues = any(
          up.name == 'restrict_new_issues' and up.value == 'true'
          for up in userprefs.prefs)
      if restrict_new_issues:
        if not any(lab.lower().startswith('restrict-view-') for lab in labels):
          labels.append(CORP_RESTRICTION_LABEL)

    field_user_views = tracker_views.MakeFieldUserViews(
        mr.cnxn, template, self.services.user)
    approval_ids = [av.approval_id for av in template.approval_values]
    field_views = tracker_views.MakeAllFieldValueViews(
        config, link_or_template_labels, [], template.field_values,
        field_user_views, parent_approval_ids=approval_ids,
        phases=template.phases)
    # TODO(jojwang): monorail:6305, remove this hack when Edit perms for field
    # values are implemented.
    field_views = [view for view in field_views
                   if view.field_name.lower() not in RESTRICTED_FLT_FIELDS]
    uneditable_fields = ezt.boolean(False)
    for fv in field_views:
      if permissions.CanEditValueForFieldDef(
          mr.auth.effective_ids, mr.perms, mr.project, fv.field_def.field_def):
        fv.is_editable = ezt.boolean(True)
      else:
        fv.is_editable = ezt.boolean(False)
        uneditable_fields = ezt.boolean(True)

    # TODO(jrobbins): remove "or []" after next release.
    (prechecked_approvals, required_approval_ids,
     phases) = issue_tmpl_helpers.GatherApprovalsPageData(
         template.approval_values or [], template.phases, config)
    approvals = [view for view in field_views if view.field_id in
                 approval_ids]

    page_data = {
        'issue_tab_mode':
            'issueEntry',
        'initial_summary':
            initial_summary,
        'template_summary':
            initial_summary,
        'clear_summary_on_click':
            ezt.boolean(
                initial_summary_must_be_edited and
                'initial_summary' not in mr.form_overrides),
        'must_edit_summary':
            ezt.boolean(initial_summary_must_be_edited),
        'initial_description':
            template.content,
        'template_name':
            template.name,
        'component_required':
            ezt.boolean(template.component_required),
        'initial_status':
            initial_status,
        'initial_owner':
            initial_owner_name,
        'owner_avail_state':
            owner_avail_state,
        'owner_avail_message_short':
            owner_avail_message_short,
        'initial_components':
            initial_components,
        'initial_cc':
            '',
        'initial_blocked_on':
            '',
        'initial_blocking':
            '',
        'initial_hotlists':
            '',
        'labels':
            labels,
        'fields':
            field_views,
        'any_errors':
            ezt.boolean(mr.errors.AnyErrors()),
        'page_perms':
            page_perms,
        'allow_attachments':
            ezt.boolean(allow_attachments),
        'max_attach_size':
            template_helpers.BytesKbOrMb(
                framework_constants.MAX_POST_BODY_SIZE),
        'offer_templates':
            ezt.boolean(offer_templates),
        'config':
            config_view,
        'restrict_to_known':
            ezt.boolean(restrict_to_known),
        'is_member':
            ezt.boolean(is_member),
        'code_font':
            ezt.boolean(code_font),
        # The following are necessary for displaying phases that come with
        # this template. These are read-only.
        'allow_edit':
            ezt.boolean(False),
        'uneditable_fields':
            uneditable_fields,
        'initial_phases':
            phases,
        'approvals':
            approvals,
        'prechecked_approvals':
            prechecked_approvals,
        'required_approval_ids':
            required_approval_ids,
        # See monorail:4692 and the use of PHASES_WITH_MILESTONES
        # in elements/flt/mr-launch-overview/mr-phase.js
        'issue_phase_names':
            list(
                {
                    phase.name.lower()
                    for phase in phases
                    if phase.name in PHASES_WITH_MILESTONES
                }),
    }

    return page_data

  def GatherHelpData(self, mr, page_data):
    """Return a dict of values to drive on-page user help.

    Args:
      mr: commonly used info parsed from the request.
      page_data: Dictionary of base and page template data.

    Returns:
      A dict of values to drive on-page user help, to be added to page_data.
    """
    help_data = super(IssueEntry, self).GatherHelpData(mr, page_data)
    dismissed = []
    if mr.auth.user_pb:
      with work_env.WorkEnv(mr, self.services) as we:
        userprefs = we.GetUserPrefs(mr.auth.user_id)
      dismissed = [
          pv.name for pv in userprefs.prefs if pv.value == 'true']
    is_privileged_domain_user = framework_bizobj.IsPriviledgedDomainUser(
        mr.auth.user_pb.email)
    if (mr.auth.user_id and
        'privacy_click_through' not in dismissed):
      help_data['cue'] = 'privacy_click_through'
    elif (mr.auth.user_id and
        'code_of_conduct' not in dismissed):
      help_data['cue'] = 'code_of_conduct'

    help_data.update({
        'is_privileged_domain_user': ezt.boolean(is_privileged_domain_user),
        })
    return help_data

  def ProcessFormData(self, mr, post_data):
    """Process the issue entry 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.
    """
    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    parsed = tracker_helpers.ParseIssueRequest(
        mr.cnxn, post_data, self.services, mr.errors, mr.project_name)

    # Updates parsed.labels and parsed.fields in place.
    field_helpers.ShiftEnumFieldsIntoLabels(
        parsed.labels, parsed.labels_remove, parsed.fields.vals,
        parsed.fields.vals_remove, config)

    labels = _DiscardUnusedTemplateLabelPrefixes(parsed.labels)

    is_member = framework_bizobj.UserIsInProject(
        mr.project, mr.auth.effective_ids)
    template = self._GetTemplate(
        mr.cnxn, config, parsed.template_name, is_member)

    (approval_values,
     phases) = issue_tmpl_helpers.FilterApprovalsAndPhases(
         template.approval_values or [], template.phases, config)

    # Issue PB with only approval_values and labels filled out, for the purpose
    # of computing applicable fields.
    partial_issue = tracker_pb2.Issue(
        approval_values=approval_values, labels=labels)
    applicable_fields = field_helpers.ListApplicableFieldDefs(
        [partial_issue], config)

    bounce_labels = parsed.labels[:]
    bounce_fields = tracker_views.MakeBounceFieldValueViews(
        parsed.fields.vals,
        parsed.fields.phase_vals,
        config,
        applicable_fields=applicable_fields)

    phase_ids_by_name = {
        phase.name.lower(): [phase.phase_id] for phase in template.phases}
    field_values = field_helpers.ParseFieldValues(
        mr.cnxn, self.services.user, parsed.fields.vals,
        parsed.fields.phase_vals, config,
        phase_ids_by_name=phase_ids_by_name)

    component_ids = tracker_helpers.LookupComponentIDs(
        parsed.components.paths, config, mr.errors)

    if not parsed.summary.strip() or parsed.summary == PLACEHOLDER_SUMMARY:
      mr.errors.summary = 'Summary is required'

    if not parsed.comment.strip():
      mr.errors.comment = 'A description is required'

    if len(parsed.comment) > tracker_constants.MAX_COMMENT_CHARS:
      mr.errors.comment = 'Comment is too long'
    if len(parsed.summary) > tracker_constants.MAX_SUMMARY_CHARS:
      mr.errors.summary = 'Summary is too long'

    if _MatchesTemplate(parsed.comment, template):
      mr.errors.comment = 'Template must be filled out.'

    if parsed.users.owner_id is None:
      mr.errors.owner = 'Invalid owner username'
    else:
      valid, msg = tracker_helpers.IsValidIssueOwner(
          mr.cnxn, mr.project, parsed.users.owner_id, self.services)
      if not valid:
        mr.errors.owner = msg

    if None in parsed.users.cc_ids:
      mr.errors.cc = 'Invalid Cc username'

    field_helpers.AssertCustomFieldsEditPerms(
        mr, config, field_values, [], [], labels, [])
    field_helpers.ApplyRestrictedDefaultValues(
        mr, config, field_values, labels, template.field_values,
        template.labels)

    # This ValidateCustomFields call is redundant with work already done
    # in CreateIssue. However, this instance passes in an ezt_errors object
    # to allow showing related errors next to the fields they happen on.
    field_helpers.ValidateCustomFields(
        mr.cnxn,
        self.services,
        field_values,
        config,
        mr.project,
        ezt_errors=mr.errors,
        issue=partial_issue)

    hotlist_pbs = ProcessParsedHotlistRefs(
        mr, self.services, parsed.hotlists.hotlist_refs)

    if not mr.errors.AnyErrors():
      with work_env.WorkEnv(mr, self.services) as we:
        try:
          if parsed.attachments:
            new_bytes_used = tracker_helpers.ComputeNewQuotaBytesUsed(
                mr.project, parsed.attachments)
            # TODO(jrobbins): Make quota be calculated and stored as
            # part of applying the comment.
            self.services.project.UpdateProject(
                mr.cnxn, mr.project.project_id,
                attachment_bytes_used=new_bytes_used)

          marked_description = tracker_helpers.MarkupDescriptionOnInput(
              parsed.comment, template.content)
          has_star = 'star' in post_data and post_data['star'] == '1'

          if approval_values:
            _AttachDefaultApprovers(config, approval_values)

          # To preserve previous behavior, do not raise filter rule errors.
          issue, _ = we.CreateIssue(
              mr.project_id,
              parsed.summary,
              parsed.status,
              parsed.users.owner_id,
              parsed.users.cc_ids,
              labels,
              field_values,
              component_ids,
              marked_description,
              blocked_on=parsed.blocked_on.iids,
              blocking=parsed.blocking.iids,
              dangling_blocked_on=[
                  tracker_pb2.DanglingIssueRef(ext_issue_identifier=ref_string)
                  for ref_string in parsed.blocked_on.federated_ref_strings
              ],
              dangling_blocking=[
                  tracker_pb2.DanglingIssueRef(ext_issue_identifier=ref_string)
                  for ref_string in parsed.blocking.federated_ref_strings
              ],
              attachments=parsed.attachments,
              approval_values=approval_values,
              phases=phases,
              raise_filter_errors=False)

          if has_star:
            we.StarIssue(issue, True)

          if hotlist_pbs:
            hotlist_ids = {hotlist.hotlist_id for hotlist in hotlist_pbs}
            issue_tuple = (issue.issue_id, mr.auth.user_id, int(time.time()),
                           '')
            self.services.features.AddIssueToHotlists(
                mr.cnxn, hotlist_ids, issue_tuple, self.services.issue,
                self.services.chart)

        except exceptions.OverAttachmentQuota:
          mr.errors.attachments = 'Project attachment quota exceeded.'
        except exceptions.InputException as e:
          if 'Undefined or deprecated component with id' in e.message:
            mr.errors.components = 'Undefined or deprecated component'

    mr.template_name = parsed.template_name
    if mr.errors.AnyErrors():
      self.PleaseCorrect(
          mr, initial_summary=parsed.summary, initial_status=parsed.status,
          initial_owner=parsed.users.owner_username,
          initial_cc=', '.join(parsed.users.cc_usernames),
          initial_components=', '.join(parsed.components.paths),
          initial_comment=parsed.comment, labels=bounce_labels,
          fields=bounce_fields, template_name=parsed.template_name,
          initial_blocked_on=parsed.blocked_on.entered_str,
          initial_blocking=parsed.blocking.entered_str,
          initial_hotlists=parsed.hotlists.entered_str,
          component_required=ezt.boolean(template.component_required))
      return

    # format a redirect url
    return framework_helpers.FormatAbsoluteURL(
        mr, urls.ISSUE_DETAIL, id=issue.local_id)

  def _GetTemplate(self, cnxn, config, template_name, is_member):
    """Tries to fetch template by name and implements default template logic
    if not found."""
    template = None
    if template_name:
      template_name = template_name.replace('+', ' ')
      template = self.services.template.GetTemplateByName(cnxn,
          template_name, config.project_id)

    if not template:
      if is_member:
        template_id = config.default_template_for_developers
      else:
        template_id = config.default_template_for_users
      template = self.services.template.GetTemplateById(cnxn, template_id)
      # If the default templates were deleted, load all and pick the first one.
      if not template:
        templates = self.services.template.GetProjectTemplates(cnxn,
            config.project_id)
        assert len(templates) > 0, 'Project has no templates!'
        template = templates[0]

    return template

  # def GetIssueEntry(self, **kwargs):
  #   return self.handler(**kwargs)

  # def PostIssueEntry(self, **kwargs):
  #   return self.handler(**kwargs)


def _AttachDefaultApprovers(config, approval_values):
  approval_defs_by_id = {ad.approval_id: ad for ad in config.approval_defs}
  for av in approval_values:
    ad = approval_defs_by_id.get(av.approval_id)
    if ad:
      av.approver_ids = ad.approver_ids[:]
    else:
      logging.info('ApprovalDef with approval_id %r could not be found',
          av.approval_id)


def _MatchesTemplate(content, template):
  content = content.strip(string.whitespace)
  template_content = template.content.strip(string.whitespace)
  diff = difflib.unified_diff(content.splitlines(),
      template_content.splitlines())
  return len('\n'.join(diff)) == 0


def _DiscardUnusedTemplateLabelPrefixes(labels):
  """Drop any labels that end in '-?'.

  Args:
    labels: a list of label strings.

  Returns:
    A list of the same labels, but without any that end with '-?'.
    Those label prefixes in the new issue templates are intended to
    prompt the user to enter some label with that prefix, but if
    nothing is entered there, we do not store anything.
  """
  return [lab for lab in labels
          if not lab.endswith('-?')]


def ProcessParsedHotlistRefs(mr, services, parsed_hotlist_refs):
  """Process a list of ParsedHotlistRefs, returning referenced hotlists.

  This function validates the given ParsedHotlistRefs using four checks; if all
  of them succeed, then it returns the corresponding hotlist protobuf objects.
  If any of them fail, it sets the appropriate error string in mr.errors, and
  returns an empty list.

  Args:
    mr: the MonorailRequest object
    services: the service manager
    parsed_hotlist_refs: a list of ParsedHotlistRef objects

  Returns:
    on valid input, a list of hotlist protobuf objects
    if a check fails (and the input is thus considered invalid), an empty list

  Side-effects:
    if any of the checks fails, set mr.errors.hotlists to a descriptive error
  """
  # Pre-processing; common pieces used by functions later.
  user_hotlist_pbs = services.features.GetHotlistsByUserID(
      mr.cnxn, mr.auth.user_id)
  user_hotlist_owners_ids = {hotlist.owner_ids[0]
      for hotlist in user_hotlist_pbs}
  user_hotlist_owners_to_emails = services.user.LookupUserEmails(
      mr.cnxn, user_hotlist_owners_ids)
  user_hotlist_emails_to_owners = {v: k
      for k, v in user_hotlist_owners_to_emails.items()}
  user_hotlist_refs_to_pbs = {
      hotlist_helpers.HotlistRef(hotlist.owner_ids[0], hotlist.name): hotlist
      for hotlist in user_hotlist_pbs }
  short_refs = list()
  full_refs = list()
  for parsed_ref in parsed_hotlist_refs:
    if parsed_ref.user_email is None:
      short_refs.append(parsed_ref)
    else:
      full_refs.append(parsed_ref)

  invalid_names = hotlist_helpers.InvalidParsedHotlistRefsNames(
      parsed_hotlist_refs, user_hotlist_pbs)
  if invalid_names:
    mr.errors.hotlists = (
        'You have no hotlist(s) named: %s' % ', '.join(invalid_names))
    return []

  ambiguous_names = hotlist_helpers.AmbiguousShortrefHotlistNames(
      short_refs, user_hotlist_pbs)
  if ambiguous_names:
    mr.errors.hotlists = (
        'Ambiguous hotlist(s) specified: %s' % ', '.join(ambiguous_names))
    return []

  # At this point, all refs' named hotlists are guaranteed to exist, and
  # short refs are guaranteed to be unambiguous;
  # therefore, short refs are also valid.
  short_refs_hotlist_names = {sref.hotlist_name for sref in short_refs}
  shortref_valid_pbs = [hotlist for hotlist in user_hotlist_pbs
      if hotlist.name in short_refs_hotlist_names]

  invalid_emails = hotlist_helpers.InvalidParsedHotlistRefsEmails(
      full_refs, user_hotlist_emails_to_owners)
  if invalid_emails:
    mr.errors.hotlists = (
        'You have no hotlist(s) owned by: %s' % ', '.join(invalid_emails))
    return []

  fullref_valid_pbs, invalid_refs = (
      hotlist_helpers.GetHotlistsOfParsedHotlistFullRefs(
        full_refs, user_hotlist_emails_to_owners, user_hotlist_refs_to_pbs))
  if invalid_refs:
    invalid_refs_readable = [':'.join(parsed_ref)
        for parsed_ref in invalid_refs]
    mr.errors.hotlists = (
        'Not in your hotlist(s): %s' % ', '.join(invalid_refs_readable))
    return []

  hotlist_pbs = shortref_valid_pbs + fullref_valid_pbs

  return hotlist_pbs
