# Copyright 2013 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.

import optparse
import os
import logging
import re

from telemetry.story import typ_expectations


class _StoryMatcher(object):
  def __init__(self, pattern):
    self._regex = None
    if pattern:
      try:
        self._regex = re.compile(pattern)
      except:
        # Provide context since the error that re module provides
        # is not user friendly.
        logging.error('We failed to compile the regex "%s"', pattern)
        raise

  def __nonzero__(self):
    return self._regex is not None

  def HasMatch(self, story):
    return self and bool(self._regex.search(story.name))


class _StoryTagMatcher(object):
  def __init__(self, tags_str):
    self._tags = [tag.strip() for tag in tags_str.split(',')
                 ] if tags_str else None

  def __nonzero__(self):
    return self._tags is not None

  def HasLabelIn(self, story):
    return self and bool(story.tags.intersection(self._tags))


class StoryFilterFactory(object):
  """This factory reads static global configuration for a StoryFilter.

  Static global configuration includes commandline flags and ProjectConfig.

  It then provides a way to create a StoryFilter by only providing
  the runtime configuration.
  """

  @classmethod
  def BuildStoryFilter(cls, benchmark_name, platform_tags,
                       abridged_story_set_tag):
    expectations = typ_expectations.StoryExpectations(benchmark_name)
    expectations.SetTags(platform_tags or [])
    if cls._expectations_file and os.path.exists(cls._expectations_file):
      with open(cls._expectations_file) as fh:
        expectations.GetBenchmarkExpectationsFromParser(fh.read())
    if not cls._run_abridged_story_set:
      abridged_story_set_tag = None
    return StoryFilter(
        expectations, abridged_story_set_tag, cls._story_filter,
        cls._story_filter_exclude,
        cls._story_tag_filter, cls._story_tag_filter_exclude,
        cls._shard_begin_index, cls._shard_end_index, cls._run_disabled_stories,
        stories=cls._stories, shard_indexes=cls._shard_indexes)

  @classmethod
  def AddCommandLineArgs(cls, parser):
    group = optparse.OptionGroup(parser, 'User story filtering options')
    group.add_option(
        '--story-filter',
        help='Use only stories whose names match the given filter regexp.')
    group.add_option(
        '--story-filter-exclude',
        help='Exclude stories whose names match the given filter regexp.')
    group.add_option(
        '--story-tag-filter',
        help='Use only stories that have any of these tags')
    group.add_option(
        '--story-tag-filter-exclude',
        help='Exclude stories that have any of these tags')
    common_story_shard_help = (
        'Indices start at 0, and have the same rules as python slices,'
        ' e.g.  [4, 5, 6, 7, 8][0:3] -> [4, 5, 6])')
    group.add_option(
        '--story-shard-begin-index', type='int', dest='story_shard_begin_index',
        help=('Beginning index of set of stories to run. If this is ommited, '
              'the starting index will be from the first story in the benchmark'
              + common_story_shard_help))
    group.add_option(
        '--story-shard-end-index', type='int', dest='story_shard_end_index',
        help=('End index of set of stories to run. Value will be '
              'rounded down to the number of stories. Negative values not'
              'allowed. If this is omited, the end index is the final story'
              'of the benchmark. '+ common_story_shard_help))
    group.add_option(
        '--story-shard-indexes', type='string', dest='story_shard_indexes',
        help=('Index ranges of sets of stories to run. (Negative values not '
              'allowed.) Each range can be a single index or a range in '
              '"begin-end" format. E.g., 2,4-6 means stories on index 2, 4, '
              '5 and 6. Ranges should be ordered. '+ common_story_shard_help))
    # This should be renamed to --also-run-disabled-stories.
    group.add_option('-d', '--also-run-disabled-tests',
                     dest='run_disabled_stories',
                     action='store_true', default=False,
                     help='Ignore expectations.config disabling.')
    # TODO(crbug.com/965158): delete this flag.
    group.add_option(
        '--run-full-story-set', action='store_true', default=False,
        help='DEPRECATED. Does not do anything. Use --run-abridged-story-set '
        'instead.')
    group.add_option(
        '--run-abridged-story-set', action='store_true', default=None,
        help='Whether to run the abridged set of stories from the benchmark '
        'instead of the whole set of stories. Note that many benchmarks do not '
        'have an abridged version: for those benchmarks this flag will have no '
        'effect.')
    group.add_option(
        '--story', action='append', dest='stories',
        help='An exact name of a story to run. These strings should be '
        'the exact values as stored in the name attribute of a story object. '
        'Passing in a story name this way will cause the story to run even '
        'if it is marked as "Skip" in the expectations config. '
        'This name does not include the benchmark name. This flag can be '
        'provided multiple times to chose to run multiple stories. '
        'The story flag is exclusive with other story selection flags.')
    parser.add_option_group(group)

  @classmethod
  def ProcessCommandLineArgs(cls, parser, args, environment=None):
    del parser
    cls._story_filter = args.story_filter
    cls._story_filter_exclude = args.story_filter_exclude
    cls._story_tag_filter = args.story_tag_filter
    cls._story_tag_filter_exclude = args.story_tag_filter_exclude
    cls._stories = args.stories
    if cls._stories:
      assert args.story_shard_begin_index is None, (
          '--story and --story-shard-begin-index are mutually exclusive.')
      assert args.story_shard_end_index is None, (
          '--story and --story-shard-end-index are mutually exclusive.')
      assert args.story_shard_indexes is None, (
          '--story and --story-shard-indexes are mutually exclusive.')
      assert args.story_filter is None, (
          '--story and --story-filter are mutually exclusive.')
      assert args.story_filter_exclude is None, (
          '--story and --story-filter-exclude are mutually exclusive.')
      assert args.story_tag_filter is None, (
          '--story and --story-tag-filter are mutually exclusive.')
      assert args.story_tag_filter_exclude is None, (
          '--story and --story-tag-filter-exclude are mutually exclusive.')
      assert args.run_abridged_story_set is None, (
          '--story and --run-abridged-story-set are mutually exclusive.')
    if args.story_shard_indexes:
      assert args.story_shard_begin_index is None, (
          '--story-shard-indexes and --story-shard-begin-index are mutually '
          'exclusive.')
      assert args.story_shard_end_index is None, (
          '--story-shard-indexes and --story-shard-end-index are mutually '
          'exclusive.')
    cls._shard_indexes = args.story_shard_indexes
    cls._shard_begin_index = args.story_shard_begin_index or 0
    cls._shard_end_index = args.story_shard_end_index
    if environment and environment.expectations_files:
      assert len(environment.expectations_files) == 1
      cls._expectations_file = environment.expectations_files[0]
    else:
      cls._expectations_file = None
    cls._run_disabled_stories = args.run_disabled_stories
    cls._run_abridged_story_set = args.run_abridged_story_set


class StoryFilter(object):
  """Logic to decide whether to run, skip, or ignore stories."""

  def __init__(
      self, expectations=None, abridged_story_set_tag=None, story_filter=None,
      story_filter_exclude=None,
      story_tag_filter=None, story_tag_filter_exclude=None,
      shard_begin_index=0, shard_end_index=None, run_disabled_stories=False,
      stories=None, shard_indexes=None):
    self._expectations = expectations
    self._include_regex = _StoryMatcher(story_filter)
    self._exclude_regex = _StoryMatcher(story_filter_exclude)
    self._include_tags = _StoryTagMatcher(story_tag_filter)
    self._exclude_tags = _StoryTagMatcher(story_tag_filter_exclude)
    self._shard_begin_index = shard_begin_index
    self._shard_end_index = shard_end_index
    self._shard_indexes = shard_indexes
    if self._shard_end_index is not None:
      if self._shard_end_index < 0:
        raise ValueError(
            'shard end index cannot be less than 0, since stories are indexed '
            'with positive numbers')
      if (self._shard_begin_index is not None and
          self._shard_end_index <= self._shard_begin_index):
        raise ValueError(
            'shard end index cannot be less than or equal to shard begin index')
    self._run_disabled_stories = run_disabled_stories
    self._abridged_story_set_tag = abridged_story_set_tag
    if stories:
      assert isinstance(stories, list)
    self._stories = stories

  def FilterStories(self, stories):
    """Filters the given stories, using filters provided in the command line.

    This filter causes stories to become completely ignored, and therefore
    they will not show up in test results output.

    Story sharding is done before exclusion and inclusion is done.

    Args:
      stories: A list of stories.

    Returns:
      A list of remaining stories.
    """
    if self._stories:
      output_stories = []
      output_stories_names = []
      for story in stories:
        if story.name in self._stories:
          output_stories.append(story)
          output_stories_names.append(story.name)
      unmatched_stories = (
          frozenset(self._stories) - frozenset(output_stories_names))
      for story in unmatched_stories:
        raise ValueError('story %s was asked for but does not exist.' % story)
      return output_stories

    if self._abridged_story_set_tag:
      stories = [story for story in stories
                 if self._abridged_story_set_tag in story.tags]
    if self._shard_indexes:
      stories = [stories[i] for i in self._GetSelectedIndexes(len(stories))]
    else:
      if self._shard_begin_index < 0:
        self._shard_begin_index = 0
      if self._shard_end_index is None:
        self._shard_end_index = len(stories)
      stories = stories[self._shard_begin_index:self._shard_end_index]
    final_stories = []
    for story in stories:
      # Exclude filters take priority.
      if self._exclude_tags.HasLabelIn(story):
        continue
      if self._exclude_regex.HasMatch(story):
        continue
      if self._include_tags and not self._include_tags.HasLabelIn(story):
        continue
      if self._include_regex and not self._include_regex.HasMatch(story):
        continue
      final_stories.append(story)
    return final_stories

  def ShouldSkip(self, story):
    """Decides whether a story should be marked skipped.

    The difference between marking a story skipped and simply not running
    it is important for tracking purposes. Officially skipped stories show
    up in test results outputs.

    Args:
      story: A story.Story object.

    Returns:
      A skip reason string if the story should be skipped, otherwise an
      empty string.
    """
    disabled = self._expectations.IsStoryDisabled(story)
    if self._stories:
      if story.name in self._stories:
        if disabled:
          logging.warn('Running story %s even though it is disabled because '
                       'it was specifically asked for by name in the --story '
                       'flag.', story.name)
        return ''
    if disabled and self._run_disabled_stories:
      logging.warning(
          'Force running a disabled story %s even though it was disabled with '
          'the following reason: %s' % (story.name, disabled))
      return ''
    return disabled

  def _GetSelectedIndexes(self, length):
    indexes = []
    index_ranges = self._shard_indexes.split(',')
    cur_end = 0
    for index_range in index_ranges:
      if '-' in index_range:
        begin, end = index_range.split('-')
        begin = int(begin) if begin else 0
        end = int(end) if end else length
        if begin >= end or begin < cur_end or end > length:
          raise ValueError(
              'The index ranges have overlaps or not sorted correctly: %s' %
              self._shard_indexes)
        indexes = indexes + list(range(begin, end))
        cur_end = end
      else:
        index = int(index_range)
        if index < cur_end:
          raise ValueError(
              'The index ranges have overlaps or not sorted correctly: %s' %
              self._shard_indexes)
        indexes.append(index)
        cur_end = index + 1
    return indexes
