package com.tiedup.remake.state.components;

import com.tiedup.remake.v2.bondage.movement.MovementStyle;
import org.jetbrains.annotations.Nullable;

/**
 * Component responsible for movement style state management.
 * Stores all per-player movement fields used exclusively by MovementStyleManager.
 *
 * <p>Thread safety: All fields are server-tick-only (PlayerTickEvent + LivingJumpEvent,
 * both on the server thread). No synchronization needed.</p>
 */
public class PlayerMovement {

    // --- Resolved style state ---
    @Nullable
    private MovementStyle activeMovementStyle;
    private float resolvedMovementSpeed = 1.0f;
    private boolean resolvedJumpDisabled = false;

    // --- Hop state ---
    private int hopCooldown = 0;
    private boolean hopStartupPending = false;
    private int hopStartupTicks = 0;
    private int hopNotMovingTicks = 0;

    // --- Crawl state ---
    private boolean pendingPoseRestore = false;

    // --- Position tracking for movement detection ---
    private double lastX;
    private double lastY;
    private double lastZ;

    public PlayerMovement() {
    }

    // --- Resolved style ---

    @Nullable
    public MovementStyle getActiveMovementStyle() {
        return activeMovementStyle;
    }

    public void setActiveMovementStyle(@Nullable MovementStyle style) {
        this.activeMovementStyle = style;
    }

    public float getResolvedMovementSpeed() {
        return resolvedMovementSpeed;
    }

    public void setResolvedMovementSpeed(float speed) {
        this.resolvedMovementSpeed = speed;
    }

    public boolean isResolvedJumpDisabled() {
        return resolvedJumpDisabled;
    }

    public void setResolvedJumpDisabled(boolean disabled) {
        this.resolvedJumpDisabled = disabled;
    }

    // --- Hop ---

    public int getHopCooldown() {
        return hopCooldown;
    }

    public void setHopCooldown(int hopCooldown) {
        this.hopCooldown = hopCooldown;
    }

    public boolean isHopStartupPending() {
        return hopStartupPending;
    }

    public void setHopStartupPending(boolean hopStartupPending) {
        this.hopStartupPending = hopStartupPending;
    }

    public int getHopStartupTicks() {
        return hopStartupTicks;
    }

    public void setHopStartupTicks(int hopStartupTicks) {
        this.hopStartupTicks = hopStartupTicks;
    }

    public int getHopNotMovingTicks() {
        return hopNotMovingTicks;
    }

    public void setHopNotMovingTicks(int hopNotMovingTicks) {
        this.hopNotMovingTicks = hopNotMovingTicks;
    }

    // --- Crawl ---

    public boolean isPendingPoseRestore() {
        return pendingPoseRestore;
    }

    public void setPendingPoseRestore(boolean pendingPoseRestore) {
        this.pendingPoseRestore = pendingPoseRestore;
    }

    // --- Position tracking ---

    public double getLastX() {
        return lastX;
    }

    public void setLastX(double lastX) {
        this.lastX = lastX;
    }

    public double getLastY() {
        return lastY;
    }

    public void setLastY(double lastY) {
        this.lastY = lastY;
    }

    public double getLastZ() {
        return lastZ;
    }

    public void setLastZ(double lastZ) {
        this.lastZ = lastZ;
    }

    /**
     * Resets all movement style state to defaults.
     * Called on death, logout, and dimension change to ensure clean re-activation.
     * Note: lastX/Y/Z are NOT reset — they track position, not style state.
     */
    public void clear() {
        this.activeMovementStyle = null;
        this.resolvedMovementSpeed = 1.0f;
        this.resolvedJumpDisabled = false;
        this.hopCooldown = 0;
        this.hopStartupPending = false;
        this.hopStartupTicks = 0;
        this.pendingPoseRestore = false;
        this.hopNotMovingTicks = 0;
    }
}
