"""Bencode parser plugin for uTorrent active torrent files."""

from dfdatetime import posix_time as dfdatetime_posix_time

from plaso.containers import events
from plaso.parsers import bencode_parser
from plaso.parsers.bencode_plugins import interface


class UTorrentEventData(events.EventData):
    """UTorrent active torrent event data.

    Attributes:
      added_time (dfdatetime.DateTimeValues): date and time the torrent was
          added to Transmission.
      caption (str): official name of package.
      destination (str): path of the downloaded file.
      downloaded_time (dfdatetime.DateTimeValues): date and time the content
          was downloaded.
      modification_times (list[dfdatetime.DateTimeValues]): modification dates
          and times.
      seedtime (int): client seed time in number of minutes.
    """

    DATA_TYPE = "p2p:bittorrent:utorrent"

    def __init__(self):
        """Initializes event data."""
        super().__init__(data_type=self.DATA_TYPE)
        self.added_time = None
        self.caption = None
        self.destination = None
        self.downloaded_time = None
        self.modification_times = None
        self.seedtime = None


class UTorrentBencodePlugin(interface.BencodePlugin):
    """Plugin to extract parse uTorrent active torrent files.

    uTorrent creates a file, resume.dat, and a backup, resume.dat.old, to for all active
    torrents. This is typically stored in the user's application data folder.

    These files, at a minimum, contain a '.fileguard' key and a dictionary with a key
    name for a particular download with a '.torrent' file extension.
    """

    NAME = "bencode_utorrent"
    DATA_FORMAT = "uTorrent active torrent file"

    # The following set is used to determine if the bencoded data is appropriate
    # for this plugin. If there's a match, the entire bencoded data block is
    # returned for analysis.
    _BENCODE_KEYS = frozenset([".fileguard"])

    def Process(self, parser_mediator, bencode_file=None, **kwargs):
        """Extracts events from an uTorrent active torrent file.

        Args:
          parser_mediator (ParserMediator): mediates interactions between parsers
              and other components, such as storage and dfVFS.
          bencode_file (Optional[BencodeFile]): bencode file.
        """
        # This will raise if unhandled keyword arguments are passed.
        super().Process(parser_mediator, **kwargs)

        root_values = bencode_file.GetValues()

        for key, value in root_values.GetValues():
            if not ".torrent" in key:
                continue

            torrent_values = bencode_parser.BencodeValues(value)

            seedtime = torrent_values.GetDecodedValue("seedtime")

            modification_times = []
            for timestamp in torrent_values.GetDecodedValue("modtimes") or []:
                # Ignore modification timestamps stored as 0.
                if timestamp:
                    date_time = dfdatetime_posix_time.PosixTime(timestamp=timestamp)
                    modification_times.append(date_time)

            event_data = UTorrentEventData()
            event_data.added_time = torrent_values.GetDateTimeValue("added_on")
            event_data.caption = torrent_values.GetDecodedValue("caption")
            event_data.destination = torrent_values.GetDecodedValue("path")
            event_data.downloaded_time = torrent_values.GetDateTimeValue("completed_on")
            event_data.modification_times = modification_times or None
            # Convert seconds to minutes.
            event_data.seedtime, _ = divmod(seedtime, 60)

        parser_mediator.ProduceEventData(event_data)


bencode_parser.BencodeParser.RegisterPlugin(UTorrentBencodePlugin)
