# 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

"""Servlets for issue tracker configuration.

These classes implement the Statuses, Labels and fields, Components, Rules, and
Views subtabs under the Process tab.  Unlike most servlet modules, this single
file holds a base class and several related servlet classes.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import itertools
import logging
import time

import ezt

from features import filterrules_helpers
from features import filterrules_views
from features import savedqueries_helpers
from framework import authdata
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from framework import framework_views
from framework import monorailrequest
from framework import permissions
from framework import servlet
from framework import urls
from proto import tracker_pb2
from tracker import field_helpers
from tracker import tracker_bizobj
from tracker import tracker_constants
from tracker import tracker_helpers
from tracker import tracker_views


class IssueAdminBase(servlet.Servlet):
  """Base class for servlets allowing project owners to configure tracker."""

  _MAIN_TAB_MODE = servlet.Servlet.MAIN_TAB_PROCESS
  _PROCESS_SUBTAB = None  # specified in subclasses

  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)
    config_view = tracker_views.ConfigView(mr, self.services, config,
        template=None, load_all_templates=True)
    open_text, closed_text = tracker_views.StatusDefsAsText(config)
    labels_text = tracker_views.LabelDefsAsText(config)

    return {
        'admin_tab_mode': self._PROCESS_SUBTAB,
        'config': config_view,
        'open_text': open_text,
        'closed_text': closed_text,
        'labels_text': labels_text,
        }

  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.
    """
    page_url = self.ProcessSubtabForm(post_data, mr)

    if page_url:
      return framework_helpers.FormatAbsoluteURL(
          mr, page_url, saved=1, ts=int(time.time()))


class AdminStatuses(IssueAdminBase):
  """Servlet allowing project owners to configure well-known statuses."""

  _PAGE_TEMPLATE = 'tracker/admin-statuses-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_STATUSES

  def ProcessSubtabForm(self, post_data, mr):
    """Process the status definition section of the admin page.

    Args:
      post_data: HTML form data for the HTTP request being processed.
      mr: commonly used info parsed from the request.

    Returns:
      The URL of the page to show after processing.
    """
    if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
      raise permissions.PermissionException(
          'Only project owners may edit the status definitions')

    wks_open_text = post_data.get('predefinedopen', '')
    wks_open_matches = framework_constants.IDENTIFIER_DOCSTRING_RE.findall(
        wks_open_text)
    wks_open_tuples = [
        (status.lstrip('#'), docstring.strip(), True, status.startswith('#'))
        for status, docstring in wks_open_matches]
    if not wks_open_tuples:
      mr.errors.open_statuses = 'A project cannot have zero open statuses'

    wks_closed_text = post_data.get('predefinedclosed', '')
    wks_closed_matches = framework_constants.IDENTIFIER_DOCSTRING_RE.findall(
        wks_closed_text)
    wks_closed_tuples = [
        (status.lstrip('#'), docstring.strip(), False, status.startswith('#'))
        for status, docstring in wks_closed_matches]
    if not wks_closed_tuples:
      mr.errors.closed_statuses = 'A project cannot have zero closed statuses'

    statuses_offer_merge_text = post_data.get('statuses_offer_merge', '')
    statuses_offer_merge = framework_constants.IDENTIFIER_RE.findall(
        statuses_offer_merge_text)

    if mr.errors.AnyErrors():
      self.PleaseCorrect(
          mr, open_text=wks_open_text, closed_text=wks_closed_text)
      return

    self.services.config.UpdateConfig(
        mr.cnxn, mr.project, statuses_offer_merge=statuses_offer_merge,
        well_known_statuses=wks_open_tuples + wks_closed_tuples)

    # TODO(jrobbins): define a "strict" mode that affects only statuses.

    return urls.ADMIN_STATUSES


class AdminLabels(IssueAdminBase):
  """Servlet allowing project owners to labels and fields."""

  _PAGE_TEMPLATE = 'tracker/admin-labels-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_LABELS

  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.
    """
    page_data = super(AdminLabels, self).GatherPageData(mr)
    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    field_def_views = [
        tracker_views.FieldDefView(fd, config)
        # TODO(jrobbins): future field-level view restrictions.
        for fd in config.field_defs
        if not fd.is_deleted]
    page_data.update({
        'field_defs': field_def_views,
        })
    return page_data

  def ProcessSubtabForm(self, post_data, mr):
    """Process changes to labels and custom field definitions.

    Args:
      post_data: HTML form data for the HTTP request being processed.
      mr: commonly used info parsed from the request.

    Returns:
      The URL of the page to show after processing.
    """
    if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
      raise permissions.PermissionException(
          'Only project owners may edit the label definitions')

    wkl_text = post_data.get('predefinedlabels', '')
    wkl_matches = framework_constants.IDENTIFIER_DOCSTRING_RE.findall(wkl_text)
    wkl_tuples = [
        (label.lstrip('#'), docstring.strip(), label.startswith('#'))
        for label, docstring in wkl_matches]
    if not wkl_tuples:
      mr.errors.label_defs = 'A project cannot have zero labels'
    label_counter = collections.Counter(wkl[0].lower() for wkl in wkl_tuples)
    for lab, count in label_counter.items():
      if count > 1:
        mr.errors.label_defs = 'Duplicate label: %s' % lab

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    field_names = [fd.field_name for fd in config.field_defs
                   if fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
                   and not fd.is_deleted]
    masked_labels = tracker_helpers.LabelsMaskedByFields(config, field_names)
    field_names_lower = [field_name.lower() for field_name in field_names]
    for wkl in wkl_tuples:
      conflict = tracker_bizobj.LabelIsMaskedByField(wkl[0], field_names_lower)
      if conflict:
        mr.errors.label_defs = (
            'Label "%s" should be defined in enum "%s"' % (wkl[0], conflict))
    wkl_tuples.extend([
        (masked.name, masked.docstring, False) for masked in masked_labels])

    excl_prefix_text = post_data.get('excl_prefixes', '')
    excl_prefixes = framework_constants.IDENTIFIER_RE.findall(excl_prefix_text)

    if mr.errors.AnyErrors():
      self.PleaseCorrect(mr, labels_text=wkl_text)
      return

    self.services.config.UpdateConfig(
        mr.cnxn, mr.project,
        well_known_labels=wkl_tuples, excl_label_prefixes=excl_prefixes)

    # TODO(jrobbins): define a "strict" mode that affects only labels.

    return urls.ADMIN_LABELS


class AdminTemplates(IssueAdminBase):
  """Servlet allowing project owners to configure templates."""

  _PAGE_TEMPLATE = 'tracker/admin-templates-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_TEMPLATES

  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.
    """
    return super(AdminTemplates, self).GatherPageData(mr)

  def ProcessSubtabForm(self, post_data, mr):
    """Process changes to new issue templates.

    Args:
      post_data: HTML form data for the HTTP request being processed.
      mr: commonly used info parsed from the request.

    Returns:
      The URL of the page to show after processing.
    """
    if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
      raise permissions.PermissionException(
          'Only project owners may edit the default templates')

    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    templates = self.services.template.GetProjectTemplates(mr.cnxn,
        config.project_id)
    default_template_id_for_developers, default_template_id_for_users = (
        self._ParseDefaultTemplateSelections(post_data, templates))
    if default_template_id_for_developers or default_template_id_for_users:
      self.services.config.UpdateConfig(
          mr.cnxn, mr.project,
          default_template_for_developers=default_template_id_for_developers,
          default_template_for_users=default_template_id_for_users)

    return urls.ADMIN_TEMPLATES

  def _ParseDefaultTemplateSelections(self, post_data, templates):
    """Parse the input for the default templates to offer users."""
    def GetSelectedTemplateID(name):
      """Find the ID of the template specified in post_data[name]."""
      if name not in post_data:
        return None
      selected_template_name = post_data[name]
      for template in templates:
        if selected_template_name == template.name:
          return template.template_id

      logging.error('User somehow selected an invalid template: %r',
                    selected_template_name)
      return None

    return (GetSelectedTemplateID('default_template_for_developers'),
            GetSelectedTemplateID('default_template_for_users'))


class AdminComponents(IssueAdminBase):
  """Servlet allowing project owners to view the list of components."""

  _PAGE_TEMPLATE = 'tracker/admin-components-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_COMPONENTS

  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.
    """
    page_data = super(AdminComponents, self).GatherPageData(mr)
    config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user,
        *[list(cd.admin_ids) + list(cd.cc_ids)
          for cd in config.component_defs])
    framework_views.RevealAllEmailsToMembers(
        mr.cnxn, self.services, mr.auth, users_by_id, mr.project)
    component_def_views = [
        tracker_views.ComponentDefView(mr.cnxn, self.services, cd, users_by_id)
        # TODO(jrobbins): future component-level view restrictions.
        for cd in config.component_defs]
    for cd in component_def_views:
      if mr.auth.email in [user.email for user in cd.admins]:
        cd.classes += 'myadmin '
      if mr.auth.email in [user.email for user in cd.cc]:
        cd.classes += 'mycc '

    page_data.update({
        'component_defs': component_def_views,
        'failed_perm': mr.GetParam('failed_perm'),
        'failed_subcomp': mr.GetParam('failed_subcomp'),
        'failed_templ': mr.GetParam('failed_templ'),
        })
    return page_data

  def _GetComponentDefs(self, _mr, post_data, config):
    """Get the config and component definitions from the request."""
    component_defs = []
    component_paths = post_data.get('delete_components').split(',')
    for component_path in component_paths:
      component_def = tracker_bizobj.FindComponentDef(component_path, config)
      component_defs.append(component_def)
    return component_defs

  def _ProcessDeleteComponent(self, mr, component_def):
    """Delete the specified component and its references."""
    self.services.issue.DeleteComponentReferences(
        mr.cnxn, component_def.component_id)
    self.services.config.DeleteComponentDef(
        mr.cnxn, mr.project_id, component_def.component_id)

  def ProcessFormData(self, mr, post_data):
    """Processes a POST command to delete components.

    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)
    component_defs = self._GetComponentDefs(mr, post_data, config)
    # Reverse the component_defs so that we start deleting from subcomponents.
    component_defs.reverse()

    # Collect errors.
    perm_errors = []
    subcomponents_errors = []
    templates_errors = []
    # Collect successes.
    deleted_components = []

    for component_def in component_defs:
      allow_edit = permissions.CanEditComponentDef(
          mr.auth.effective_ids, mr.perms, mr.project, component_def, config)
      if not allow_edit:
        perm_errors.append(component_def.path)

      subcomponents = tracker_bizobj.FindDescendantComponents(
          config, component_def)
      if subcomponents:
        subcomponents_errors.append(component_def.path)

      templates = self.services.template.TemplatesWithComponent(
          mr.cnxn, component_def.component_id)
      if templates:
        templates_errors.append(component_def.path)

      allow_delete = allow_edit and not subcomponents and not templates
      if allow_delete:
        self._ProcessDeleteComponent(mr, component_def)
        deleted_components.append(component_def.path)
        # Refresh project config after the component deletion.
        config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)

    return framework_helpers.FormatAbsoluteURL(
        mr, urls.ADMIN_COMPONENTS, ts=int(time.time()),
        failed_perm=','.join(perm_errors),
        failed_subcomp=','.join(subcomponents_errors),
        failed_templ=','.join(templates_errors),
        deleted=','.join(deleted_components))


class AdminViews(IssueAdminBase):
  """Servlet for project owners to set default columns, axes, and sorting."""

  _PAGE_TEMPLATE = 'tracker/admin-views-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_VIEWS

  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.
    """
    page_data = super(AdminViews, self).GatherPageData(mr)
    with mr.profiler.Phase('getting canned queries'):
      canned_queries = self.services.features.GetCannedQueriesByProjectID(
          mr.cnxn, mr.project_id)
      canned_query_views = [
          savedqueries_helpers.SavedQueryView(sq, idx + 1, None, None)
          for idx, sq in enumerate(canned_queries)]

    page_data.update({
        'canned_queries': canned_query_views,
        'new_query_indexes': list(range(
            len(canned_queries) + 1, savedqueries_helpers.MAX_QUERIES + 1)),
        'issue_notify': mr.project.issue_notify_address,
        'max_queries': savedqueries_helpers.MAX_QUERIES,
        })
    return page_data

  def ProcessSubtabForm(self, post_data, mr):
    """Process the Views subtab.

    Args:
      post_data: HTML form data for the HTTP request being processed.
      mr: commonly used info parsed from the request.

    Returns:
      The URL of the page to show after processing.
    """
    if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
      raise permissions.PermissionException(
          'Only project owners may edit the default views')
    existing_queries = savedqueries_helpers.ParseSavedQueries(
        mr.cnxn, post_data, self.services.project)
    added_queries = savedqueries_helpers.ParseSavedQueries(
        mr.cnxn, post_data, self.services.project, prefix='new_')
    canned_queries = existing_queries + added_queries

    list_prefs = _ParseListPreferences(post_data)

    if mr.errors.AnyErrors():
      self.PleaseCorrect(mr)
      return

    self.services.config.UpdateConfig(
        mr.cnxn, mr.project, list_prefs=list_prefs)
    self.services.features.UpdateCannedQueries(
        mr.cnxn, mr.project_id, canned_queries)

    return urls.ADMIN_VIEWS


def _ParseListPreferences(post_data):
  """Parse the part of a project admin form about artifact list preferences."""
  default_col_spec = ''
  if 'default_col_spec' in post_data:
    default_col_spec = post_data['default_col_spec']
  # Don't allow empty colum spec
  if not default_col_spec:
    default_col_spec = tracker_constants.DEFAULT_COL_SPEC
  col_spec_words = monorailrequest.ParseColSpec(
      default_col_spec, max_parts=framework_constants.MAX_COL_PARTS)
  col_spec = ' '.join(word for word in col_spec_words)

  default_sort_spec = ''
  if 'default_sort_spec' in post_data:
    default_sort_spec = post_data['default_sort_spec']
  sort_spec_words = monorailrequest.ParseColSpec(default_sort_spec)
  sort_spec = ' '.join(sort_spec_words)

  x_attr_str = ''
  if 'default_x_attr' in post_data:
    x_attr_str = post_data['default_x_attr']
  x_attr_words = monorailrequest.ParseColSpec(x_attr_str)
  x_attr = ''
  if x_attr_words:
    x_attr = x_attr_words[0]

  y_attr_str = ''
  if 'default_y_attr' in post_data:
    y_attr_str = post_data['default_y_attr']
  y_attr_words = monorailrequest.ParseColSpec(y_attr_str)
  y_attr = ''
  if y_attr_words:
    y_attr = y_attr_words[0]

  member_default_query = ''
  if 'member_default_query' in post_data:
    member_default_query = post_data['member_default_query']

  return col_spec, sort_spec, x_attr, y_attr, member_default_query


class AdminRules(IssueAdminBase):
  """Servlet allowing project owners to configure filter rules."""

  _PAGE_TEMPLATE = 'tracker/admin-rules-page.ezt'
  _PROCESS_SUBTAB = servlet.Servlet.PROCESS_TAB_RULES

  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(AdminRules, 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.
    """
    page_data = super(AdminRules, self).GatherPageData(mr)
    rules = self.services.features.GetFilterRules(
        mr.cnxn, mr.project_id)
    users_by_id = framework_views.MakeAllUserViews(
        mr.cnxn, self.services.user,
        [rule.default_owner_id for rule in rules],
        *[rule.add_cc_ids for rule in rules])
    framework_views.RevealAllEmailsToMembers(
        mr.cnxn, self.services, mr.auth, users_by_id, mr.project)
    rule_views = [filterrules_views.RuleView(rule, users_by_id)
                  for rule in rules]

    for idx, rule_view in enumerate(rule_views):
      rule_view.idx = idx + 1  # EZT has no loop index, so we set idx.

    page_data.update({
        'rules': rule_views,
        'new_rule_indexes': (
            list(range(len(rules) + 1, filterrules_helpers.MAX_RULES + 1))),
        'max_rules': filterrules_helpers.MAX_RULES,
        })
    return page_data

  def ProcessSubtabForm(self, post_data, mr):
    """Process the Rules subtab.

    Args:
      post_data: HTML form data for the HTTP request being processed.
      mr: commonly used info parsed from the request.

    Returns:
      The URL of the page to show after processing.
    """
    old_rules = self.services.features.GetFilterRules(mr.cnxn, mr.project_id)
    rules = filterrules_helpers.ParseRules(
        mr.cnxn, post_data, self.services.user, mr.errors)
    new_rules = filterrules_helpers.ParseRules(
        mr.cnxn, post_data, self.services.user, mr.errors, prefix='new_')
    rules.extend(new_rules)

    if mr.errors.AnyErrors():
      self.PleaseCorrect(mr)
      return

    config = self.services.features.UpdateFilterRules(
        mr.cnxn, mr.project_id, rules)

    if old_rules != rules:
      logging.info('recomputing derived fields')
      config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
      filterrules_helpers.RecomputeAllDerivedFields(
          mr.cnxn, self.services, mr.project, config)

    return urls.ADMIN_RULES
