package com.tiedup.remake.state;

import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;

/**
 * Capture, leash, and transport interface for kidnapped entities.
 *
 * <p>Covers the capture lifecycle: being captured by a captor, being freed,
 * being transferred to another captor, and querying capture state.</p>
 *
 * @see IRestrainableEntity
 * @see IBondageState
 * @see IRestrainable
 */
public interface ICapturable extends IRestrainableEntity {
    // CAPTURE LIFECYCLE

    /**
     * Capture this entity by the given captor.
     *
     * <p><b>Prerequisites:</b></p>
     * <ul>
     *   <li>Must be tied up OR have collar with captor as owner</li>
     *   <li>Must not already be captured ({@link #isCaptive()} == false)</li>
     *   <li>Captor must allow capture ({@link ICaptor#canCapture(IRestrainable)})</li>
     * </ul>
     *
     * <p><b>Process for Players:</b></p>
     * <ol>
     *   <li>Validate conditions (tied up or has owner's collar)</li>
     *   <li>Transfer any existing captives to new captor (if allowed)</li>
     *   <li>Create LeashProxyEntity that follows the player</li>
     *   <li>Attach leash from proxy to captor entity</li>
     *   <li>Add captive to captor's captive list</li>
     * </ol>
     *
     * <p><b>Process for NPCs:</b></p>
     * <ol>
     *   <li>Validate conditions</li>
     *   <li>Use vanilla setLeashedTo() directly on the NPC</li>
     * </ol>
     *
     *
     * @param captor The captor attempting to capture
     * @return true if capture succeeded, false otherwise
     */
    boolean getCapturedBy(ICaptor captor);

    /**
     * Free this captive from capture.
     * Equivalent to {@code free(true)}.
     *
     * <p>This will:</p>
     * <ul>
     *   <li>Despawn the transport entity</li>
     *   <li>Drop the lead item</li>
     *   <li>Remove from captor's captive list</li>
     * </ul>
     */
    void free();

    /**
     * Free this captive from capture with transport state option.
     *
     * @param transportState If true, despawn the transport entity. If false, keep it (for transfer).
     */
    void free(boolean transportState);

    /**
     * Transfer this captive to a new captor.
     * Current captor loses the captive, new captor gains it.
     *
     * <p>Only works if current captor allows captive transfer
     * ({@link ICaptor#allowCaptiveTransfer()} == true).</p>
     *
     *
     * @param newCaptor The new captor to transfer to
     */
    void transferCaptivityTo(ICaptor newCaptor);

    // STATE QUERIES - CAPTURE

    /**
     * Check if this entity can be captured.
     *
     * <p><b>From original code (PlayerBindState.java:195-225):</b></p>
     * <ul>
     *   <li>If tied up: Always capturable</li>
     *   <li>If NOT tied up: Only capturable if has collar AND collar has captor as owner</li>
     * </ul>
     *
     * @return true if capturable
     */
    boolean isEnslavable();

    /**
     * Check if this entity is currently captured (attached by leash).
     *
     * <p><b>For Players:</b> Returns true when LeashProxyEntity is attached and leashed to captor</p>
     * <p><b>For NPCs:</b> Returns true when vanilla leash is attached</p>
     *
     *
     * @return true if captured (has leash holder)
     */
    boolean isCaptive();

    /**
     * Check if this entity can be tied up (not already restrained).
     *
     * @return true if entity can accept bind items
     */
    boolean canBeTiedUp();

    /**
     * Check if this entity is tied to a pole (immobilized).
     *
     * @return true if tied to a static pole entity
     */
    boolean isTiedToPole();

    /**
     * Tie this entity to the closest fence/pole within range.
     * Searches for fence blocks near the entity's current position.
     *
     * @param searchRadius The radius in blocks to search for fences
     * @return true if successfully tied to a pole
     */
    boolean tieToClosestPole(int searchRadius);

    /**
     * Check if this entity can be auto-kidnapped by events.
     * Used by EntityKidnapper AI to determine valid targets.
     *
     * @return true if can be targeted by kidnapping events
     */
    boolean canBeKidnappedByEvents();

    /**
     * Get the current captor (the entity holding the leash).
     *
     *
     * @return The captor, or null if not captured
     */
    ICaptor getCaptor();

    /**
     * Get the leash proxy or transport entity for this captive.
     *
     * <p><b>For Players:</b> Returns the LeashProxyEntity following the player</p>
     * <p><b>For NPCs:</b> Returns null (NPCs use vanilla leash directly)</p>
     *
     * @return The proxy/transport entity, or null if not applicable
     */
    @Nullable
    Entity getTransport();
}
