package com.tiedup.remake.state.components;

import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.state.hosts.IPlayerBindStateHost;
import com.tiedup.remake.state.struggle.StruggleBinds;
import com.tiedup.remake.state.struggle.StruggleCollar;
import net.minecraft.world.entity.player.Player;

/**
 * Component responsible for struggle mechanics and resistance management.
 *
 * Single Responsibility: Struggle state and resistance tracking
 * Complexity: MEDIUM (volatile fields, animation coordination)
 * Risk: MEDIUM (thread-safety requirements)
 *
 * Threading: Uses host's volatile fields for animation state (isStruggling, struggleStartTick)
 *
 * Note: StruggleBinds and StruggleCollar require PlayerBindState parameter.
 * Since PlayerBindState implements IPlayerBindStateHost, we can safely cast.
 */
public class PlayerStruggle {

    private final IPlayerBindStateHost host;
    private final PlayerBindState state; // Cast reference for struggle system

    private final StruggleBinds struggleBindState;
    private final StruggleCollar struggleCollarState;

    public PlayerStruggle(IPlayerBindStateHost host) {
        this.host = host;
        // Safe cast: PlayerBindState implements IPlayerBindStateHost
        this.state = (PlayerBindState) host;

        // Initialize sub-states for struggling
        this.struggleBindState = new StruggleBinds();
        this.struggleCollarState = new StruggleCollar();
    }

    // ========== Struggle Methods ==========

    /**
     * Entry point for the Struggle logic (Key R).
     * Distributes effort between Binds and Collar.
     *
     * Thread Safety: Must be called from the server thread (packet handlers use enqueueWork).
     */
    public void struggle() {
        if (struggleBindState != null) struggleBindState.struggle(state);
        if (struggleCollarState != null) struggleCollarState.struggle(state);
    }

    /**
     * Restores resistance to base values when a master tightens the ties.
     *
     * Thread Safety: Must be called from the server thread.
     */
    public void tighten(Player tightener) {
        if (struggleBindState != null) struggleBindState.tighten(
            tightener,
            state
        );
        if (struggleCollarState != null) struggleCollarState.tighten(
            tightener,
            state
        );
    }

    /**
     * Get the StruggleBinds instance for external access (mini-game system).
     */
    public StruggleBinds getStruggleBinds() {
        return struggleBindState;
    }

    /**
     * Set a cooldown on struggle attempts (used after mini-game exhaustion).
     * @param seconds Cooldown duration in seconds
     */
    public void setStruggleCooldown(int seconds) {
        if (
            struggleBindState != null &&
            host.getPlayer() != null &&
            host.getLevel() != null
        ) {
            struggleBindState.setExternalCooldown(seconds, host.getLevel());
        }
    }

    /**
     * v2.5: Check if struggle cooldown is active.
     * @return true if cooldown is active (cannot struggle yet)
     */
    public boolean isStruggleCooldownActive() {
        return (
            struggleBindState != null && struggleBindState.isCooldownActive()
        );
    }

    /**
     * v2.5: Get remaining struggle cooldown in seconds.
     * @return Remaining seconds, or 0 if no cooldown
     */
    public int getStruggleCooldownRemaining() {
        return struggleBindState != null
            ? struggleBindState.getRemainingCooldownSeconds()
            : 0;
    }

    // ========== Animation Control ==========
    // Note: Animation state (isStruggling, struggleStartTick) is managed by host
    // via IPlayerBindStateHost interface (volatile fields for thread-safety)

    /**
     * Check if struggle animation should stop (duration expired).
     * @param currentTick Current game time tick
     * @return True if animation has been playing for >= 80 ticks
     */
    public boolean shouldStopStruggling(long currentTick) {
        if (!host.isStruggling()) return false;
        return (
            (currentTick - host.getStruggleStartTick()) >=
            com.tiedup.remake.util.GameConstants.STRUGGLE_ANIMATION_DURATION_TICKS
        );
    }
}
