"""Parser for the Microsoft File History ESE database."""

from plaso.containers import events
from plaso.parsers import esedb
from plaso.parsers.esedb_plugins import interface


class FileHistoryNamespaceEventData(events.EventData):
  """File history namespace table event data.

  Attributes:
    creation_time (dfdatetime.DateTimeValues): file entry creation date
        and time.
    file_attribute (int): file attribute.
    identifier (str): identifier.
    modification_time (dfdatetime.DateTimeValues): file entry last modification
        date and time.
    original_filename (str): original file name.
    parent_identifier (str): parent identifier.
    usn_number (int): USN number.
  """

  DATA_TYPE = 'windows:file_history:namespace'

  def __init__(self):
    """Initializes event data."""
    super().__init__(
        data_type=self.DATA_TYPE)
    self.creation_time = None
    self.file_attribute = None
    self.identifier = None
    self.modification_time = None
    self.original_filename = None
    self.parent_identifier = None
    self.usn_number = None


class FileHistoryESEDBPlugin(interface.ESEDBPlugin):
  """Parses a File History ESE database file."""

  NAME = 'file_history'
  DATA_FORMAT = 'Windows 8 File History ESE database file'

  # TODO: Add support for other tables as well, backupset, file, library, etc.
  REQUIRED_TABLES = {
      'backupset': '',
      'file': '',
      'library': '',
      'namespace': 'ParseNameSpace'}

  def _GetDictFromStringsTable(self, parser_mediator, table):
    """Build a dictionary of the value in the strings table.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfVFS.
      table (pyesedb.table): strings table.

    Returns:
      dict[str,object]: values per column name.
    """
    if not table:
      return {}

    record_values = {}
    for record in table.records:
      if parser_mediator.abort:
        break

      if record.get_number_of_values() != 2:
        continue

      identification = self._GetRecordValue(record, 0)
      filename = self._GetRecordValue(record, 1)

      if not identification:
        continue
      record_values[identification] = filename

    return record_values

  def ParseNameSpace(
      self, parser_mediator, cache=None, database=None, table=None,
      **unused_kwargs):
    """Parses the namespace table.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfVFS.
      cache (Optional[ESEDBCache]): cache.
      database (Optional[ESEDatabase]): ESE database.
      table (Optional[pyesedb.table]): table.

    Raises:
      ValueError: if the database or table value is missing.
    """
    if database is None:
      raise ValueError('Missing database value.')

    if table is None:
      raise ValueError('Missing table value.')

    strings = cache.GetResults('strings')
    if not strings:
      esedb_table = database.GetTableByName('string')
      strings = self._GetDictFromStringsTable(parser_mediator, esedb_table)
      cache.SetResults('strings', strings)

    for record_index, esedb_record in enumerate(table.records):
      if parser_mediator.abort:
        break

      record_values = self._GetRecordValues(
          parser_mediator, table.name, record_index, esedb_record)

      event_data = FileHistoryNamespaceEventData()
      event_data.creation_time = self._GetFiletimeRecordValue(
           record_values, 'fileCreated')
      event_data.file_attribute = record_values.get('fileAttrib')
      event_data.identifier = record_values.get('id')
      event_data.modification_time = self._GetFiletimeRecordValue(
          record_values, 'fileModified')
      event_data.original_filename = strings.get(event_data.identifier)
      event_data.parent_identifier = record_values.get('parentId')
      event_data.usn_number = record_values.get('usn')

      parser_mediator.ProduceEventData(event_data)


esedb.ESEDBParser.RegisterPlugin(FileHistoryESEDBPlugin)
