@Override
	public void handlePieceCompleted(SharingPeer peer, Piece piece) {
		synchronized (this.torrent) {
			if (piece.isValid()) {
				// Make sure the piece is marked as completed in the torrent
				// Note: this is required because the order the
				// PeerActivityListeners are called is not defined, and we
				// might be called before the torrent's piece completion
				// handler is.
				this.torrent.markCompleted(piece);
				logger.debug("Completed download of " + piece + ", now has " +
						this.torrent.getCompletedPieces().cardinality() + "/" +
						this.torrent.getPieceCount() + " pieces.");

				// Send a HAVE message to all connected peers
				Message have = Message.HaveMessage.craft(piece.getIndex());
				for (SharingPeer remote : this.connected.values()) {
					remote.send(have);
				}

				// Force notify after each piece is completed to propagate download
				// completion information (or new seeding state)
				this.setChanged();
				this.notifyObservers(this.state);
			}

			if (this.torrent.isComplete()) {
				logger.info("Last piece validated and completed, " +
						"download is complete.");
				this.seed();
			}
		}
	}