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

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

import java.util.Arrays;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.entity.EntitySnapshot;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Component;

public class SnapshotBuffer implements Component<EntityStore>
{
    private EntitySnapshot[] snapshots;
    private int currentTickIndex;
    private int oldestTickIndex;
    private int currentIndex;
    
    public SnapshotBuffer() {
        this.currentTickIndex = Integer.MIN_VALUE;
        this.oldestTickIndex = Integer.MIN_VALUE;
        this.currentIndex = -1;
    }
    
    public static ComponentType<EntityStore, SnapshotBuffer> getComponentType() {
        return EntityModule.get().getSnapshotBufferComponentType();
    }
    
    @Nonnull
    public EntitySnapshot getSnapshotClamped(final int tickIndex) {
        if (this.currentIndex == -1) {
            throw new IllegalStateException("Snapshots not initialized");
        }
        int relIndex = tickIndex - this.currentTickIndex;
        final int maxRel = this.oldestTickIndex - this.currentTickIndex;
        if (relIndex > 0) {
            throw new IllegalArgumentException("Tick index is in the future");
        }
        if (relIndex < maxRel) {
            relIndex = maxRel;
        }
        return this.getSnapshotRelative(relIndex);
    }
    
    @Nullable
    public EntitySnapshot getSnapshot(final int tickIndex) {
        if (this.currentIndex == -1) {
            return null;
        }
        final int relIndex = tickIndex - this.currentTickIndex;
        final int maxRel = this.oldestTickIndex - this.currentTickIndex;
        if (relIndex > 0) {
            throw new IllegalArgumentException("Tick index is in the future");
        }
        if (relIndex < maxRel) {
            return null;
        }
        return this.getSnapshotRelative(relIndex);
    }
    
    private EntitySnapshot getSnapshotRelative(final int relIndex) {
        int index = this.currentIndex + relIndex;
        index = (this.snapshots.length + index) % this.snapshots.length;
        return this.snapshots[index];
    }
    
    public void storeSnapshot(final int tickIndex, @Nonnull final Vector3d position, @Nonnull final Vector3f bodyRotation) {
        if (this.currentIndex != -1 && this.currentTickIndex != tickIndex - 1) {
            this.currentIndex = -1;
            this.currentTickIndex = Integer.MIN_VALUE;
            this.oldestTickIndex = Integer.MIN_VALUE;
        }
        if (this.currentIndex == -1) {
            this.oldestTickIndex = tickIndex;
        }
        this.currentTickIndex = tickIndex;
        ++this.currentIndex;
        this.currentIndex %= this.snapshots.length;
        final int maxRel = this.currentTickIndex - this.oldestTickIndex;
        if (maxRel >= this.snapshots.length) {
            ++this.oldestTickIndex;
        }
        final EntitySnapshot snapshot = this.snapshots[this.currentIndex];
        snapshot.init(position, bodyRotation);
    }
    
    public void resize(final int newLength) {
        if (newLength <= 0) {
            throw new IllegalArgumentException("New size is too small: " + newLength);
        }
        if (this.snapshots != null && newLength == this.snapshots.length) {
            return;
        }
        if (this.snapshots == null) {
            this.snapshots = new EntitySnapshot[newLength];
            for (int i = 0; i < this.snapshots.length; ++i) {
                this.snapshots[i] = new EntitySnapshot();
            }
        }
        else {
            final int oldLength = this.snapshots.length;
            this.snapshots = Arrays.copyOf(this.snapshots, newLength);
            for (int j = oldLength; j < newLength; ++j) {
                this.snapshots[j] = new EntitySnapshot();
            }
        }
        this.currentIndex = -1;
        this.currentTickIndex = Integer.MIN_VALUE;
        this.oldestTickIndex = Integer.MIN_VALUE;
    }
    
    public boolean isInitialized() {
        return this.currentIndex != -1;
    }
    
    public int getCurrentTickIndex() {
        return this.currentTickIndex;
    }
    
    public int getOldestTickIndex() {
        return this.oldestTickIndex;
    }
    
    @Nonnull
    @Override
    public Component<EntityStore> clone() {
        final SnapshotBuffer buffer = new SnapshotBuffer();
        if (this.snapshots == null || this.currentIndex == -1) {
            return buffer;
        }
        buffer.resize(this.snapshots.length);
        for (int i = this.oldestTickIndex; i <= this.currentTickIndex; ++i) {
            final EntitySnapshot snap = this.getSnapshot(i);
            buffer.storeSnapshot(i, snap.getPosition(), snap.getBodyRotation());
        }
        return buffer;
    }
}
