"""Tagging file."""

import io
import re

from plaso.filters import event_filter
from plaso.lib import errors


class TaggingFile:
  """Tagging file that defines one or more event tagging rules."""

  # A line with no indent is a tag name.
  _TAG_LABEL_LINE = re.compile(r'^(\w+)')

  # A line with leading indent is one of the rules for the preceding tag.
  _TAG_RULE_LINE = re.compile(r'^\s+(.+)')

  # If any of these words are in the query then it's probably objectfilter.
  _OBJECTFILTER_WORDS = re.compile(
      r'\s(is|isnot|equals|notequals|inset|notinset|contains|notcontains)\s')

  def __init__(self, path):
    """Initializes a tagging file.

    Args:
      path (str): path to a file that contains one or more event tagging rules.
    """
    super().__init__()
    self._path = path

  def GetEventTaggingRules(self):
    """Retrieves the event tagging rules from the tagging file.

    Returns:
      dict[str, EventObjectFilter]: tagging rules, that consists of one or more
          filter objects per label.

    Raises:
      TaggingFileError: if a filter expression cannot be compiled.
    """
    rules_per_label = {}

    label_name = None
    with io.open(self._path, 'r', encoding='utf-8') as tagging_file:
      for line in tagging_file.readlines():
        line = line.rstrip()

        stripped_line = line.lstrip()
        if not stripped_line:
          label_name = None
          continue

        if stripped_line[0] == '#':
          continue

        if not line[0].isspace():
          label_name = line
          rules_per_label[label_name] = []

        elif label_name:
          rules_per_label[label_name].append(stripped_line)

    filter_objects_per_label = {}

    for label_name, rules in rules_per_label.items():
      filter_object = event_filter.EventObjectFilter()

      try:
        filter_rule = ' OR '.join([f'({rule:s})' for rule in rules])
        filter_object.CompileFilter(filter_rule)
      except errors.ParseError as exception:
        raise errors.TaggingFileError((
            f'Unable to compile filter for label: {label_name:s} with error: '
            f'{exception!s}'))

      # TODO: change other code remove list around filter_object
      filter_objects_per_label[label_name] = [filter_object]

    return filter_objects_per_label
