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

package com.hypixel.hytale.builtin.teleport.components;

import java.util.Collection;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.modules.entity.teleport.Teleport;
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.Ref;
import java.util.ArrayDeque;
import com.hypixel.hytale.builtin.teleport.TeleportPlugin;
import com.hypixel.hytale.component.ComponentType;
import javax.annotation.Nonnull;
import java.util.Deque;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Component;

public class TeleportHistory implements Component<EntityStore>
{
    private static final int MAX_TELEPORT_HISTORY = 100;
    private static final Message MESSAGE_COMMANDS_TELEPORT_NOT_FURTHER;
    private static final Message MESSAGE_COMMANDS_TELEPORT_WORLD_NOT_LOADED;
    @Nonnull
    private final Deque<Waypoint> back;
    @Nonnull
    private final Deque<Waypoint> forward;
    
    @Nonnull
    public static ComponentType<EntityStore, TeleportHistory> getComponentType() {
        return TeleportPlugin.get().getTeleportHistoryComponentType();
    }
    
    public TeleportHistory() {
        this.back = new ArrayDeque<Waypoint>();
        this.forward = new ArrayDeque<Waypoint>();
    }
    
    public void forward(@Nonnull final Ref<EntityStore> ref, final int count) {
        final Store<EntityStore> store = ref.getStore();
        go(store, ref, this.forward, this.back, count, true);
    }
    
    public void back(@Nonnull final Ref<EntityStore> ref, final int count) {
        final Store<EntityStore> store = ref.getStore();
        go(store, ref, this.back, this.forward, count, false);
    }
    
    public int getForwardSize() {
        return this.forward.size();
    }
    
    public int getBackSize() {
        return this.back.size();
    }
    
    private static void go(@Nonnull final Store<EntityStore> store, @Nonnull final Ref<EntityStore> ref, @Nonnull final Deque<Waypoint> from, @Nonnull final Deque<Waypoint> to, final int count, final boolean isForward) {
        if (count <= 0) {
            throw new IllegalArgumentException(String.valueOf(count));
        }
        final PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
        assert playerRef != null;
        Waypoint point = null;
        int i = 0;
        while (i < count) {
            if (from.isEmpty()) {
                if (point == null) {
                    playerRef.sendMessage(TeleportHistory.MESSAGE_COMMANDS_TELEPORT_NOT_FURTHER);
                    return;
                }
                break;
            }
            else {
                point = from.pop();
                to.push(point);
                ++i;
            }
        }
        if (point == null) {
            throw new NullPointerException(to.toString());
        }
        final World targetWorld = Universe.get().getWorld(point.world);
        if (targetWorld == null) {
            playerRef.sendMessage(TeleportHistory.MESSAGE_COMMANDS_TELEPORT_WORLD_NOT_LOADED);
        }
        else {
            to.push(point);
            final Teleport teleportComponent = Teleport.createForPlayer(targetWorld, point.position, point.rotation);
            store.addComponent(ref, Teleport.getComponentType(), teleportComponent);
            final Vector3d pos = point.position;
            final int remainingInDirection = from.size();
            final int totalInOtherDirection = to.size() - 1;
            if (point.message != null && !point.message.isEmpty()) {
                playerRef.sendMessage((isForward ? Message.translation("server.commands.teleport.teleportedForwardToWaypoint") : Message.translation("server.commands.teleport.teleportedBackToWaypoint")).param("name", point.message).param("x", pos.getX()).param("y", pos.getY()).param("z", pos.getZ()).param("remaining", remainingInDirection).param("otherDirection", totalInOtherDirection));
            }
            else {
                playerRef.sendMessage((isForward ? Message.translation("server.commands.teleport.teleportedForwardToCoordinates") : Message.translation("server.commands.teleport.teleportedBackToCoordinates")).param("x", pos.getX()).param("y", pos.getY()).param("z", pos.getZ()).param("remaining", remainingInDirection).param("otherDirection", totalInOtherDirection));
            }
        }
    }
    
    public void append(@Nonnull final World world, @Nonnull final Vector3d pos, @Nonnull final Vector3f rotation, @Nonnull final String key) {
        this.back.push(new Waypoint(world.getName(), pos, rotation, key));
        this.forward.clear();
        while (this.back.size() > 100) {
            this.back.removeLast();
        }
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "TeleportHistory{back=" + String.valueOf(this.back) + ", forward=" + String.valueOf(this.forward);
    }
    
    @Nonnull
    @Override
    public Component<EntityStore> clone() {
        final TeleportHistory cloned = new TeleportHistory();
        cloned.back.addAll(this.back);
        cloned.forward.addAll(this.forward);
        return cloned;
    }
    
    static {
        MESSAGE_COMMANDS_TELEPORT_NOT_FURTHER = Message.translation("server.commands.teleport.notFurther");
        MESSAGE_COMMANDS_TELEPORT_WORLD_NOT_LOADED = Message.translation("server.commands.teleport.worldNotLoaded");
    }
    
    public static class Waypoint
    {
        private final String world;
        private final Vector3d position;
        private final Vector3f rotation;
        private final String message;
        
        public Waypoint(@Nonnull final String world, @Nonnull final Vector3d position, @Nonnull final Vector3f rotation, @Nonnull final String message) {
            this.world = world;
            this.position = position;
            this.rotation = rotation;
            this.message = message;
        }
        
        @Nonnull
        @Override
        public String toString() {
            return "Waypoint{world='" + this.world + "', position=" + String.valueOf(this.position) + ", rotation=" + String.valueOf(this.rotation) + ", message='" + this.message + "'}";
        }
    }
}
