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

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

from features import filterrules_helpers
from features import filterrules_views
from features import savedqueries_helpers
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 mrproto import tracker_pb2
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,
        'can_edit_project':
            permissions.CanEditProjectConfig(mr, self.services) or None,
    }

  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 permissions.CanEditProjectConfig(mr, self.services):
      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

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

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


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 permissions.CanEditProjectConfig(mr, self.services):
      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

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

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


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 permissions.CanEditProjectConfig(mr, self.services):
      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'))

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

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


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, self.services, 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))

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

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


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 permissions.CanEditProjectConfig(mr, self.services):
      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 GetAdminViewsPage(self, **kwargs):
    return self.handler(**kwargs)

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


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 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.
    """
    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

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

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