// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.entity;

import com.hypixel.hytale.server.core.modules.interaction.interaction.operation.Operation;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import java.util.logging.Level;
import com.hypixel.hytale.protocol.InteractionState;
import com.hypixel.hytale.server.core.meta.IMetaRegistry;
import javax.annotation.Nullable;
import com.hypixel.hytale.protocol.InteractionSyncData;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.meta.DynamicMetaStore;
import com.hypixel.hytale.logger.HytaleLogger;

public class InteractionEntry
{
    private static final HytaleLogger LOGGER;
    private final int index;
    @Nonnull
    private final DynamicMetaStore<Interaction> metaStore;
    private long timestamp;
    private long simulationTimestamp;
    private final InteractionSyncData serverState;
    private InteractionSyncData simulationState;
    @Nullable
    private InteractionSyncData clientState;
    private long waitingForSyncData;
    private long waitingForServerFinished;
    private long waitingForClientFinished;
    private boolean useSimulationState;
    private boolean desynced;
    private boolean shouldSendInitial;
    
    public InteractionEntry(final int index, final int counter, final int rootInteraction) {
        this.serverState = new InteractionSyncData();
        this.shouldSendInitial = true;
        this.index = index;
        this.metaStore = new DynamicMetaStore<Interaction>(null, Interaction.META_REGISTRY);
        this.serverState.operationCounter = counter;
        this.serverState.rootInteraction = rootInteraction;
        this.serverState.state = InteractionState.NotFinished;
    }
    
    public int getIndex() {
        return this.index;
    }
    
    public int nextForkId() {
        return this.serverState.totalForks++;
    }
    
    public int getNextForkId() {
        return this.serverState.totalForks;
    }
    
    @Nonnull
    public InteractionSyncData getState() {
        return this.useSimulationState ? this.getSimulationState() : this.getServerState();
    }
    
    public void setUseSimulationState(final boolean useSimulationState) {
        this.useSimulationState = useSimulationState;
    }
    
    public float getTimeInSeconds(final long tickTime) {
        final long timestamp = this.getTimestamp();
        if (timestamp == 0L) {
            return 0.0f;
        }
        final long diff = tickTime - timestamp;
        return diff / 1.0E9f;
    }
    
    public void setTimestamp(long timestamp, final float shift) {
        timestamp -= (long)(shift * 1.0E9f);
        if (this.useSimulationState) {
            this.simulationTimestamp = timestamp;
            return;
        }
        this.timestamp = timestamp;
    }
    
    public long getTimestamp() {
        return this.useSimulationState ? this.simulationTimestamp : this.timestamp;
    }
    
    public boolean isUseSimulationState() {
        return this.useSimulationState;
    }
    
    @Nullable
    public InteractionSyncData getClientState() {
        return this.clientState;
    }
    
    @Nonnull
    public DynamicMetaStore<Interaction> getMetaStore() {
        return this.metaStore;
    }
    
    public int getServerDataHashCode() {
        final InteractionSyncData serverData = this.getState();
        final float progress = serverData.progress;
        serverData.progress = (float)(int)progress;
        final int hashCode = serverData.hashCode();
        serverData.progress = progress;
        return hashCode;
    }
    
    @Nonnull
    public InteractionSyncData getServerState() {
        return this.serverState;
    }
    
    @Nonnull
    public InteractionSyncData getSimulationState() {
        if (this.simulationState == null) {
            this.simulationState = new InteractionSyncData();
            this.simulationState.operationCounter = this.serverState.operationCounter;
            this.simulationState.rootInteraction = this.serverState.rootInteraction;
            this.simulationState.state = InteractionState.NotFinished;
        }
        return this.simulationState;
    }
    
    public boolean setClientState(@Nullable final InteractionSyncData clientState) {
        if (clientState != null && (clientState.operationCounter != this.serverState.operationCounter || clientState.rootInteraction != this.serverState.rootInteraction)) {
            final HytaleLogger.Api ctx = InteractionEntry.LOGGER.at(Level.FINE);
            if (ctx.isEnabled()) {
                final RootInteraction root = RootInteraction.getAssetMap().getAsset(this.serverState.rootInteraction);
                final Operation op = root.getOperation(this.serverState.operationCounter);
                final Operation innerOp = op.getInnerOperation();
                String info;
                if (innerOp instanceof final Interaction interaction) {
                    info = interaction.getId() + " (" + interaction.getClass().getSimpleName();
                }
                else {
                    info = String.valueOf(op) + " (" + op.getClass().getSimpleName();
                }
                ctx.log("%d: Client/Server desync %d != %d, %d != %d (for %s)", this.index, this.serverState.operationCounter, clientState.operationCounter, this.serverState.rootInteraction, clientState.rootInteraction, info);
            }
            return false;
        }
        this.clientState = clientState;
        return true;
    }
    
    public long getWaitingForSyncData() {
        return this.waitingForSyncData;
    }
    
    public void setWaitingForSyncData(final long waitingForSyncData) {
        this.waitingForSyncData = waitingForSyncData;
    }
    
    public long getWaitingForServerFinished() {
        return this.waitingForServerFinished;
    }
    
    public void setWaitingForServerFinished(final long waitingForServerFinished) {
        this.waitingForServerFinished = waitingForServerFinished;
    }
    
    public long getWaitingForClientFinished() {
        return this.waitingForClientFinished;
    }
    
    public void setWaitingForClientFinished(final long waitingForClientFinished) {
        this.waitingForClientFinished = waitingForClientFinished;
    }
    
    public boolean consumeDesyncFlag() {
        final boolean flag = this.desynced;
        this.desynced = false;
        return flag;
    }
    
    public void flagDesync() {
        this.desynced = true;
    }
    
    public boolean consumeSendInitial() {
        final boolean flag = this.shouldSendInitial;
        this.shouldSendInitial = false;
        return flag;
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "InteractionEntry{index=" + this.index + ", metaStore=" + String.valueOf(this.metaStore) + ", timestamp=" + this.timestamp + ", getTimeInSeconds()=" + this.getTimeInSeconds(System.nanoTime()) + ", simulationTimestamp=" + this.simulationTimestamp + ", serverState=" + String.valueOf(this.serverState) + ", simulationState=" + String.valueOf(this.simulationState) + ", clientState=" + String.valueOf(this.clientState) + ", waitingForSyncData=" + this.waitingForSyncData + ", waitingForServerFinished=" + this.waitingForServerFinished + ", waitingForClientFinished=" + this.waitingForClientFinished + ", useSimulationState=" + this.useSimulationState + ", desynced=" + this.desynced;
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
