"""Plist parser plugin for MacOS software update plist files."""

from plaso.containers import events
from plaso.parsers import plist
from plaso.parsers.plist_plugins import interface


class MacOSSoftwareUpdateEventData(events.EventData):
    """MacOS software update event data.

    Attributes:
      full_update_time (dfdatetime.DateTimeValues): date and time of last
          full MacOS software update.
      recommended_updates (list[str]): recommended updates.
      system_version (str): operating system version.
      update_time (dfdatetime.DateTimeValues): date and time of last
          MacOS software update.
    """

    DATA_TYPE = "macos:software_updata:entry"

    def __init__(self):
        """Initializes event data."""
        super().__init__(data_type=self.DATA_TYPE)
        self.full_update_time = None
        self.recommended_updates = None
        self.system_version = None
        self.update_time = None


class MacOSSoftwareUpdatePlistPlugin(interface.PlistPlugin):
    """Plist parser plugin for MacOS software update plist files.

    Further details about the extracted fields:
      LastFullSuccessfulDate:
        timestamp when MacOS was full update.
      LastSuccessfulDate:
        timestamp when MacOS was partially update.
    """

    NAME = "macos_software_update"
    DATA_FORMAT = "MacOS software update plist file"

    PLIST_PATH_FILTERS = frozenset(
        [interface.PlistPathFilter("com.apple.SoftwareUpdate.plist")]
    )

    PLIST_KEYS = frozenset(
        [
            "LastFullSuccessfulDate",
            "LastSuccessfulDate",
            "LastAttemptSystemVersion",
            "LastUpdatesAvailable",
            "LastRecommendedUpdatesAvailable",
            "RecommendedUpdates",
        ]
    )

    # pylint: disable=arguments-differ
    def _ParsePlist(self, parser_mediator, match=None, **unused_kwargs):
        """Extracts relevant MacOS update entries.

        Args:
          parser_mediator (ParserMediator): mediates interactions between parsers
              and other components, such as storage and dfVFS.
          match (Optional[dict[str: object]]): keys extracted from PLIST_KEYS.
        """
        last_full_successful_date = match.get("LastFullSuccessfulDate")
        last_successful_date = match.get("LastSuccessfulDate")

        recommended_updates = []
        if match.get("LastUpdatesAvailable"):
            for update_property in match.get("RecommendedUpdates", []):
                identifier = update_property.get("Identifier")
                product_key = update_property.get("Product Key")

                recommended_updates.append(f"{identifier:s} ({product_key:s})")

        event_data = MacOSSoftwareUpdateEventData()
        event_data.full_update_time = self._GetDateTimeValueFromPlistKey(
            match, "LastFullSuccessfulDate"
        )
        event_data.recommended_updates = recommended_updates or None
        event_data.system_version = match.get("LastAttemptSystemVersion")

        # Only set update_time if it differs from full_update_time.
        if last_successful_date and last_successful_date != last_full_successful_date:
            event_data.update_time = self._GetDateTimeValueFromPlistKey(
                match, "LastSuccessfulDate"
            )

        parser_mediator.ProduceEventData(event_data)


plist.PlistParser.RegisterPlugin(MacOSSoftwareUpdatePlistPlugin)
