"""Parser for Microsoft Edge load statistics database."""

from dfdatetime import webkit_time as dfdatetime_webkit_time

from plaso.containers import events
from plaso.parsers import sqlite
from plaso.parsers.sqlite_plugins import interface


class EdgeLoadStatisticsResourceEventData(events.EventData):
  """Microsoft Edge load statistics resource event data.

  Attributes:
    last_update: Last update time of resource, cached or not.
    query (str): query that created the event data.
    resource_hostname: External domain of the resource that was loaded
    resource_type: Integer descriptor of resource type
    top_level_hostname: Source domain that initiated resource load
  """

  DATA_TYPE = 'edge:resources:load_statistics'

  def __init__(self):
    """Initializes event data."""
    super().__init__(data_type=self.DATA_TYPE)
    self.last_update = None
    self.query = None
    self.resource_hostname = None
    self.resource_type = None
    self.top_level_hostname = None


class EdgeLoadStatisticsPlugin(interface.SQLitePlugin):
  """SQLite parser plugin for Microsoft Edge load statistics database."""

  NAME = 'edge_load_statistics'
  DESCRIPTION = 'Parser for Microsoft Edge load_statistics.db'

  QUERIES = [
      ('SELECT top_level_hostname, resource_hostname, resource_type, '
       'last_update FROM load_statistics', 'ParseResourceRow')]

  REQUIRED_STRUCTURE = {
      'load_statistics': frozenset([
          'top_level_hostname', 'resource_hostname', 'resource_url_hash', 
          'resource_type', 'last_update']),
      'meta':frozenset([
          'key','value']),
      'redirect_statistics':frozenset([
          'source_hostname','destination_hostname',
          'is_top_level_document','last_update'])}

  SCHEMAS = [{
     'load_statistics': (
          'CREATE TABLE load_statistics(top_level_hostname TEXT,'
          'resource_hostname TEXT, resource_url_hash TEXT, resource_type'
          'INTEGER, last_update INTEGER NOT NULL,'
          'UNIQUE(top_level_hostname,resource_url_hash))'),
      'meta': (
          'CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,'
          'value LONGVARCHAR)'),
      'redirect_statistics': (
          'CREATE TABLE redirect_statistics(source_hostname TEXT,'
          'destination_hostname TEXT, is_top_level_document INTEGER NOT'
          'NULL, last_update INTEGER NOT NULL, UNIQUE(source_hostname,desti'
          'nation_hostname,is_top_level_document))')}]

  def _GetWebKitDateTimeRowValue(self, query_hash, row, value_name):
    """Retrieves a WebKit date and time value from the row.

    Args:
      query_hash (int): hash of the query, that uniquely identifies the query
          that produced the row.
      row (sqlite3.Row): row.
      value_name (str): name of the value.

    Returns:
      dfdatetime.WebKitTime: date and time value or None if not available.
    """
    timestamp = self._GetRowValue(query_hash, row, value_name)
    if timestamp is None:
      return None

    return dfdatetime_webkit_time.WebKitTime(timestamp=timestamp)

  def ParseResourceRow(self, parser_mediator, query, row, **unused_kwargs):
    """Parses a row from the database.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfVFS.
      query (str): query that created the row.
      row (sqlite3.Row): row resulting from query.
    """
    # Note that pysqlite does not accept a Unicode string in row['string'] and
    # will raise "IndexError: Index must be int or string".
    query_hash = hash(query)

    event_data = EdgeLoadStatisticsResourceEventData()
    event_data.last_update = self._GetWebKitDateTimeRowValue(
        query_hash, row, 'last_update')
    event_data.query = query
    event_data.resource_hostname = self._GetRowValue(
        query_hash, row, 'resource_hostname')
    event_data.resource_type = self._GetRowValue(
        query_hash, row, 'resource_type')
    event_data.top_level_hostname = self._GetRowValue(
        query_hash, row, 'top_level_hostname')

    parser_mediator.ProduceEventData(event_data)


sqlite.SQLiteParser.RegisterPlugin(EdgeLoadStatisticsPlugin)
