=pod

=encoding utf-8

=head1 NAME

Net::BitTorrent::Torrent - High-level Torrent/Swarm Manager

=head1 SYNOPSIS

    my $torrent = $client->add_magnet( $uri, './downloads');

    # Monitor progress
    $torrent->on( piece_verified => sub ($t, $index) {
        printf "[%s] Progress: %.2f%%\n", $t->name, $t->progress;
    });

    # Wait for metadata (if magnet)
    $torrent->on( status_update => sub ($t, $stats) {
        if ($t->is_metadata_complete) {
            say "Metadata received for " . $t->name;
            # Torrent will automatically transition state if start() was called
        }
    });

    # Example: Acting as a partial seeder
    $torrent->on( started => sub ($t) {
        if ($t->is_seed) {
            say "Initial seeding complete, continuing to share...";
        }
    });

    $torrent->start( );

=head1 DESCRIPTION

C<Net::BitTorrent::Torrent> represents a single BitTorrent swarm. It orchestrates the interaction between peers, the
piece picker, and the storage layer.

=head2 Lifecycle States:

=over

=item * B<STATE_STOPPED>: No network activity.

=item * B<STATE_METADATA>: (Magnet mode) Fetching the info dictionary via B<BEP 09>.

=item * B<STATE_STARTING>: Initializing storage and announcing to trackers.

=item * B<STATE_RUNNING>: Actively downloading and uploading data.

=item * B<STATE_PAUSED>: Connections are maintained, but no data is transferred.

=back

=head1 METHODS

=head2 C<start( )>

Starts the swarm.

    $torrent->start();

This method triggers DHT lookups, tracker announces, and local peer discovery. It transitions the swarm to the STARTING
or METADATA state.

=head2 C<stop( )>

Stops the swarm.

    $torrent->stop();

This method stops network activity, disconnects peers, and flushes storage.

=head2 C<pause( )>

Pauses the swarm.

    $torrent->pause();

This method keeps connections alive but stops data transfer.

=head2 C<resume( )>

Resumes a paused swarm.

    $torrent->resume();

This method resumes data transfer on existing connections.

=head2 C<on( $event, $callback )>

Registers a callback for swarm events.

    $torrent->on(piece_verified => sub ($t, $idx) { ... });

This method allows listening for events specific to this torrent.

Expected parameters:

=over

=item C<$event>

The name of the event to listen for. Supported events: C<piece_verified>, C<piece_failed>, C<status_update>,
C<peer_discovered>, C<started>, C<stopped>, C<paused>, C<resumed>.

=item C<$callback>

The code reference to execute when the event is emitted.

=back

=head2 C<name( )>

Returns a human-readable name for the torrent.

    say 'Downloading: ' . $torrent->name;

This method returns the name from the metadata if available, or a hex infohash as a fallback.

=head2 C<progress( )>

Returns the download completion percentage.

    printf 'Done: %.2f%%\r', $torrent->progress;

This method returns a floating-point number between 0.0 and 100.0 representing the completion status.

=head2 C<is_finished( )>

Checks if the download is complete.

    say 'Download complete!' if $torrent->is_finished;

This method returns true if the download is 100% complete and verified.

=head2 C<is_seed( )>

Checks if the client is seeding.

    if ($torrent->is_seed) { ... }

This method returns true if the client has all pieces and is acting as a seeder.

=head2 C<is_metadata_complete( )>

Checks if metadata is loaded.

    if ($torrent->is_metadata_complete) { ... }

This method returns true if the info dictionary is available.

=head2 C<is_running( )>

Checks if the swarm is active.

    if ($torrent->is_running) { ... }

This method returns true if the state is STARTING, RUNNING, or METADATA.

=head2 C<primary_pieces_root( )>

Returns the pieces root for the first file (v2).

    my $root = $torrent->primary_pieces_root();

This method returns the SHA-256 Merkle tree root for the primary file in a BitTorrent v2 torrent.

=head2 C<set_piece_priority( $index, $priority )>

Sets the priority for a specific piece.

    $torrent->set_piece_priority( 5, 0 );

This method allows adjusting the download priority of individual pieces. A priority of 0 means the piece will not be
downloaded.

Expected parameters:

=over

=item C<$index>

The zero-based piece index.

=item C<$priority>

The priority level (0 = do not download, 1 = normal, higher values = higher priority).

=back

=head2 C<set_picking_strategy( $strategy )>

Sets the piece picking algorithm.

    $torrent->set_picking_strategy(PICK_SEQUENTIAL);

This method changes how the client selects pieces to download. Available strategies are defined in
L<Net::BitTorrent::Types>.

Expected parameters:

=over

=item C<$strategy>

The strategy constant to use (e.g., C<PICK_RAREST_FIRST>, C<PICK_SEQUENTIAL>).

=back

=head2 C<infohash_v1( )>

Returns the v1 infohash.

    my $ih = $torrent->infohash_v1;

This method returns the 20-byte binary SHA-1 infohash for BitTorrent v1. Returns C<undef> if not available.

=head2 C<infohash_v2( )>

Returns the v2 infohash.

    my $ih = $torrent->infohash_v2;

This method returns the 32-byte binary SHA-256 infohash for BitTorrent v2. Returns C<undef> if not available.

=head2 C<files( )>

Returns a list of file paths.

    my $paths = $torrent->files;

This method returns an array reference containing the absolute paths of all files in the torrent.

=head2 C<discovered_peers( )>

Returns a list of known peers.

    my $peers = $torrent->discovered_peers;

This method returns an array reference of peer structures discovered via various mechanisms.

=head2 C<dump_state( )>

Exports the torrent state.

    my $state = $torrent->dump_state;

This method returns a data structure representing the current state of the torrent, suitable for persistence.

=head2 C<load_state( $state )>

Restores the torrent state.

    $torrent->load_state($state);

This method restores the torrent state from a previously dumped structure.

Expected parameters:

=over

=item C<$state>

The state data structure (hash reference).

=back

=head2 C<get_superseed_piece( $peer )>

Retrieves a piece index for super-seeding.

    my $idx = $torrent->get_superseed_piece($peer);

This method selects a piece to offer to a peer when in super-seeding mode (BEP 16).

Expected parameters:

=over

=item C<$peer>

The L<Net::BitTorrent::Peer> object.

=back

=head2 C<metadata_received_count( )>

Returns the number of metadata bytes received.

    my $count = $torrent->metadata_received_count();

This method returns the total number of bytes of the info dictionary currently received.

=head2 C<set_limit_up( $val )>

Sets the upload rate limit for this torrent.

    $torrent->set_limit_up( 512 * 1024 );

This method sets the maximum upload rate in bytes per second for this specific swarm.

Expected parameters:

=over

=item C<$val>

The limit in bytes per second. Use 0 for unlimited.

=back

=head2 C<set_limit_down( $val )>

Sets the download rate limit for this torrent.

    $torrent->set_limit_down( 1024 * 1024 );

This method sets the maximum download rate in bytes per second for this specific swarm.

Expected parameters:

=over

=item C<$val>

The limit in bytes per second. Use 0 for unlimited.

=back

=head2 C<can_read( $amount )>

Checks if a download amount is allowed by rate limits.

    my $allowed = $torrent->can_read( 16384 );

This method checks both global and per-torrent rate limits and returns the amount that can be consumed.

Expected parameters:

=over

=item C<$amount>

The requested number of bytes to download.

=back

=head2 C<can_write( $amount )>

Checks if an upload amount is allowed by rate limits.

    my $allowed = $torrent->can_write( 16384 );

This method checks both global and per-torrent rate limits and returns the amount that can be consumed.

Expected parameters:

=over

=item C<$amount>

The requested number of bytes to upload.

=back

=head2 C<tick( [$delta] )>

Performs periodic maintenance for the swarm.

    $torrent->tick( 0.1 );

This method handles peer connections, piece requests, choking logic, and tracker announces for this swarm.

Expected parameters:

=over

=item C<$delta> - optional

The time elapsed since the last tick in seconds. Defaults to 0.1.

=back

=head2 C<add_peer( $peer )>

Adds a discovered peer to the swarm.

    $torrent->add_peer({ ip => '1.2.3.4', port => 6881 });

This method adds a peer to the list of potential connections.

Expected parameters:

=over

=item C<$peer>

A hash reference or object containing C<ip> and C<port>.

=back

=head2 C<add_dht_nodes( $nodes )>

Adds DHT nodes to the search frontier.

    $torrent->add_dht_nodes( $nodes_list );

This method adds nodes discovered via the DHT to the search frontier for this torrent.

Expected parameters:

=over

=item C<$nodes>

An array reference of node structures.

=back

=head2 C<ban_peer( $ip, $port )>

Bans a peer from the swarm.

    $torrent->ban_peer( '1.2.3.4', 6881 );

This method removes a peer and prevents reconnection for a period of time.

Expected parameters:

=over

=item C<$ip>

The IP address of the peer.

=item C<$port>

The port number of the peer.

=back

=head2 C<register_peer_object( $peer_obj )>

Registers an active peer connection.

    $torrent->register_peer_object( $peer );

This method registers a L<Net::BitTorrent::Peer> object as an active connection for this swarm.

Expected parameters:

=over

=item C<$peer_obj>

The L<Net::BitTorrent::Peer> object.

=back

=head2 C<start_dht_lookup( )>

Manually triggers a DHT lookup for peers.

    $torrent->start_dht_lookup();

This method initiates an iterative DHT search for peers on all supported infohashes.

=head2 C<peer_id( )>

Returns the local peer ID used for this torrent.

    my $id = $torrent->peer_id();

This method returns the 20-byte binary peer ID.

=head2 C<trackers( )>

Returns the list of trackers.

    my $trackers = $torrent->trackers();

This method returns an array reference of L<Net::BitTorrent::Tracker::Base> objects.

=head1 Specifications

=over

=item * B<BEP 03>: Core Peer Wire Protocol

=item * B<BEP 06>: Fast Extension

=item * B<BEP 09>: Metadata Exchange

=item * B<BEP 11>: Peer Exchange (PEX)

=item * B<BEP 16>: Super-seeding Logic

=item * B<BEP 33>: DHT Scraping

=item * B<BEP 52>: BitTorrent v2 (Hybrid support)

=back

=head1 AUTHOR

Sanko Robinson E<lt>sanko@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2008-2026 by Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

=cut
