"""Task attribute container definition."""

import time
import uuid

from acstore.containers import interface
from acstore.containers import manager

from plaso.lib import definitions


class Task(interface.AttributeContainer):
    """Task attribute container.

    A task describes a piece of work for a multi processing worker process
    for example a task to process a path specification or to analyze an event.

    Attributes:
      aborted (bool): True if the task was aborted.
      completion_time (int): time that the task was completed. Contains the
          number of micro seconds since January 1, 1970, 00:00:00 UTC.
      file_entry_type (str): dfVFS type of the file entry the path specification
          is referencing.
      has_retry (bool): True if the task was previously abandoned and a retry
          task was created, False otherwise.
      identifier (str): unique identifier of the task.
      last_processing_time (int): the last time the task was marked as being
          processed as number of milliseconds since January 1, 1970, 00:00:00 UTC.
      merge_priority (int): priority used for the task storage file merge, where
          a lower value indicates a higher priority to merge.
      path_spec (dfvfs.PathSpec): path specification.
      session_identifier (str): the identifier of the session the task is part of.
      start_time (int): time that the task was started. Contains the number
          of micro seconds since January 1, 1970, 00:00:00 UTC.
      storage_file_size (int): size of the storage file in bytes.
      storage_format (str): the format the task results are to be stored in.
    """

    CONTAINER_TYPE = "task"

    SCHEMA = {
        "aborted": "bool",
        "completion_time": "int",
        "file_entry_type": "str",
        "has_retry": "bool",
        "identifier": "str",
        "last_processing_time": "int",
        "merge_priority": "int",
        "path_spec": "dfvfs.PathSpec",
        "session_identifier": "str",
        "start_time": "int",
        "storage_file_size": "int",
        "storage_format": "str",
    }

    def __init__(self, session_identifier=None):
        """Initializes a task attribute container.

        Args:
          session_identifier (Optional[str]): identifier of the session the task
              is part of.
        """
        super().__init__()
        self.aborted = False
        self.completion_time = None
        self.file_entry_type = None
        self.has_retry = False
        self.identifier = f"{uuid.uuid4().hex:s}"
        self.last_processing_time = None
        self.merge_priority = None
        self.path_spec = None
        self.session_identifier = session_identifier
        self.start_time = int(time.time() * definitions.MICROSECONDS_PER_SECOND)
        self.storage_file_size = None
        self.storage_format = None

    # This method is necessary for heap sort.
    def __lt__(self, other):
        """Compares if the task attribute container is less than the other.

        Args:
          other (Task): task attribute container to compare to.

        Returns:
          bool: True if the task attribute container is less than the other.
        """
        return self.identifier < other.identifier

    def CreateRetryTask(self):
        """Creates a new task to retry a previously abandoned task.

        The retry task will have a new identifier but most of the attributes
        will be a copy of the previously abandoned task.

        Returns:
          Task: a task to retry a previously abandoned task.
        """
        retry_task = Task(session_identifier=self.session_identifier)
        retry_task.file_entry_type = self.file_entry_type
        retry_task.merge_priority = self.merge_priority
        retry_task.path_spec = self.path_spec
        retry_task.storage_file_size = self.storage_file_size
        retry_task.storage_format = self.storage_format

        self.has_retry = True

        return retry_task

    def UpdateProcessingTime(self):
        """Updates the processing time to now."""
        self.last_processing_time = int(
            time.time() * definitions.MICROSECONDS_PER_SECOND
        )


manager.AttributeContainersManager.RegisterAttributeContainer(Task)
