"""JSON-L parser plugin for Docker container log files."""

from dfdatetime import time_elements as dfdatetime_time_elements

from plaso.containers import events
from plaso.parsers import jsonl_parser
from plaso.parsers.jsonl_plugins import interface


class DockerContainerLogEventData(events.EventData):
    """Docker container log event data.

    Attributes:
      container_identifier (str): identifier of the container (SHA256).
      log_source (str): log source.
      message_body (str): message body.
      written_time (dfdatetime.DateTimeValues): date and time the entry was
          written.
    """

    DATA_TYPE = "docker:container:log:entry"

    def __init__(self):
        """Initializes event data."""
        super().__init__(data_type=self.DATA_TYPE)
        self.container_identifier = None
        self.log_source = None
        self.message_body = None
        self.written_time = None


class DockerContainerLogJSONLPlugin(interface.JSONLPlugin):
    """JSON-L parser plugin for Docker container log files.

    This parser handles per Docker container log files stored in:
    DOCKER_DIR/containers/<container_identifier>/<container_identifier>-json.log
    """

    NAME = "docker_container_log"
    DATA_FORMAT = "Docker container log file"

    def __init__(self):
        """Initializes a JSON-L parser plugin."""
        super().__init__()
        self._container_identifier = None

    def _GetContainerIdentifierFromPath(self, parser_mediator):
        """Extracts a container identifier from a path.

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

        Returns:
          str: container identifier.
        """
        file_entry = parser_mediator.GetFileEntry()
        file_system = file_entry.GetFileSystem()

        path_segments = file_system.SplitPath(file_entry.path_spec.location)
        # TODO: validate format of container identifier.
        return path_segments[-2]

    def _ParseRecord(self, parser_mediator, json_dict):
        """Parses a Docker container log record.

        Args:
          parser_mediator (ParserMediator): mediates interactions between parsers and
              other components, such as storage and dfVFS.
          json_dict (dict): JSON dictionary of the log record.
        """
        if not self._container_identifier:
            self._container_identifier = self._GetContainerIdentifierFromPath(
                parser_mediator
            )

        # TODO: escape special characters in the message body.
        message_body = self._GetJSONValue(json_dict, "log", default_value="")

        date_time, corrupted = self._ParseISO8601DateTimeString(
            parser_mediator, json_dict, "time"
        )
        event_data = DockerContainerLogEventData()
        event_data.container_identifier = self._container_identifier
        event_data.message_body = message_body or None
        event_data.log_source = self._GetJSONValue(json_dict, "stream")
        event_data.written_time = date_time

        parser_mediator.ProduceEventData(event_data, corrupted=corrupted)

    def CheckRequiredFormat(self, json_dict):
        """Check if the log record has the minimal structure required by the plugin.

        Args:
          json_dict (dict): JSON dictionary of the log record.

        Returns:
          bool: True if this is the correct parser, False otherwise.
        """
        log = json_dict.get("log") or None
        stream = json_dict.get("stream") or None
        time = json_dict.get("time") or None

        if None in (log, stream, time):
            return False

        date_time = dfdatetime_time_elements.TimeElementsInMicroseconds()

        try:
            date_time.CopyFromStringISO8601(time)
        except ValueError:
            return False

        self._container_identifier = None

        return True


jsonl_parser.JSONLParser.RegisterPlugin(DockerContainerLogJSONLPlugin)
