// Generated by delombok at Tue Dec 16 19:35:27 UTC 2025
package net.md_5.bungee.api.event;

import com.google.common.base.Preconditions;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.plugin.Event;
import net.md_5.bungee.api.plugin.Plugin;

/**
 * Represents an event which depends on the result of asynchronous operations.
 *
 * @param <T> Type of this event
 */
public class AsyncEvent<T> extends Event {
    private final Callback<T> done;
    private final Map<Plugin, AtomicInteger> intents = new ConcurrentHashMap<>();
    private final AtomicBoolean fired = new AtomicBoolean();
    private final AtomicInteger latch = new AtomicInteger();

    @Override
    @SuppressWarnings("unchecked")
    public void postCall() {
        if (latch.get() == 0) {
            done.done((T) this, null);
        }
        fired.set(true);
    }

    /**
     * Register an intent that this plugin will continue to perform work on a
     * background task, and wishes to let the event proceed once the registered
     * background task has completed. Multiple intents can be registered by a
     * plugin, but the plugin must complete the same amount of intents for the
     * event to proceed.
     *
     * @param plugin the plugin registering this intent
     */
    public void registerIntent(Plugin plugin) {
        Preconditions.checkState(!fired.get(), "Event %s has already been fired", this);
        AtomicInteger intentCount = intents.get(plugin);
        if (intentCount == null) {
            intents.put(plugin, new AtomicInteger(1));
        } else {
            intentCount.incrementAndGet();
        }
        latch.incrementAndGet();
    }

    /**
     * Notifies this event that this plugin has completed an intent and wishes
     * to let the event proceed once all intents have been completed.
     *
     * @param plugin a plugin which has an intent registered for this event
     */
    @SuppressWarnings("unchecked")
    public void completeIntent(Plugin plugin) {
        AtomicInteger intentCount = intents.get(plugin);
        Preconditions.checkState(intentCount != null && intentCount.get() > 0, "Plugin %s has not registered intents for event %s", plugin, this);
        intentCount.decrementAndGet();
        if (fired.get()) {
            if (latch.decrementAndGet() == 0) {
                done.done((T) this, null);
            }
        } else {
            latch.decrementAndGet();
        }
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public AsyncEvent(final Callback<T> done) {
        this.done = done;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public java.lang.String toString() {
        return "AsyncEvent(super=" + super.toString() + ", done=" + this.done + ", intents=" + this.intents + ", fired=" + this.fired + ", latch=" + this.latch + ")";
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (!(o instanceof AsyncEvent)) return false;
        final AsyncEvent<?> other = (AsyncEvent<?>) o;
        if (!other.canEqual((java.lang.Object) this)) return false;
        if (!super.equals(o)) return false;
        final java.lang.Object this$done = this.done;
        final java.lang.Object other$done = other.done;
        if (this$done == null ? other$done != null : !this$done.equals(other$done)) return false;
        final java.lang.Object this$intents = this.intents;
        final java.lang.Object other$intents = other.intents;
        if (this$intents == null ? other$intents != null : !this$intents.equals(other$intents)) return false;
        final java.lang.Object this$fired = this.fired;
        final java.lang.Object other$fired = other.fired;
        if (this$fired == null ? other$fired != null : !this$fired.equals(other$fired)) return false;
        final java.lang.Object this$latch = this.latch;
        final java.lang.Object other$latch = other.latch;
        if (this$latch == null ? other$latch != null : !this$latch.equals(other$latch)) return false;
        return true;
    }

    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    protected boolean canEqual(final java.lang.Object other) {
        return other instanceof AsyncEvent;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    @lombok.Generated
    public int hashCode() {
        final int PRIME = 59;
        int result = super.hashCode();
        final java.lang.Object $done = this.done;
        result = result * PRIME + ($done == null ? 43 : $done.hashCode());
        final java.lang.Object $intents = this.intents;
        result = result * PRIME + ($intents == null ? 43 : $intents.hashCode());
        final java.lang.Object $fired = this.fired;
        result = result * PRIME + ($fired == null ? 43 : $fired.hashCode());
        final java.lang.Object $latch = this.latch;
        result = result * PRIME + ($latch == null ? 43 : $latch.hashCode());
        return result;
    }
}
