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

package com.hypixel.hytale.builtin.portals.resources;

import com.hypixel.hytale.protocol.packets.interface_.PortalState;
import com.hypixel.hytale.protocol.packets.interface_.PortalDef;
import com.hypixel.hytale.protocol.packets.interface_.UpdatePortal;
import javax.annotation.Nullable;
import com.hypixel.hytale.builtin.portals.components.voidevent.config.VoidEventConfig;
import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import com.hypixel.hytale.server.core.universe.world.World;
import java.util.Map;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import com.hypixel.hytale.server.core.asset.type.portalworld.PortalType;
import com.hypixel.hytale.builtin.portals.PortalsPlugin;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.math.vector.Transform;
import java.util.UUID;
import java.util.Set;
import com.hypixel.hytale.builtin.portals.integrations.PortalGameplayConfig;
import com.hypixel.hytale.builtin.portals.integrations.PortalRemovalCondition;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Resource;

public class PortalWorld implements Resource<EntityStore>
{
    private String portalTypeId;
    private int timeLimitSeconds;
    private PortalRemovalCondition worldRemovalCondition;
    private PortalGameplayConfig storedGameplayConfig;
    private Set<UUID> diedInWorld;
    private Set<UUID> seesUi;
    private Transform spawnPoint;
    private Ref<EntityStore> voidEventRef;
    
    public static ResourceType<EntityStore, PortalWorld> getResourceType() {
        return PortalsPlugin.getInstance().getPortalResourceType();
    }
    
    public void init(final PortalType portalType, final int timeLimitSeconds, final PortalRemovalCondition removalCondition, final PortalGameplayConfig gameplayConfig) {
        this.portalTypeId = portalType.getId();
        this.timeLimitSeconds = timeLimitSeconds;
        this.worldRemovalCondition = removalCondition;
        this.storedGameplayConfig = gameplayConfig;
        this.diedInWorld = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
        this.seesUi = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
    }
    
    public PortalType getPortalType() {
        if (this.portalTypeId == null) {
            return null;
        }
        return PortalType.getAssetMap().getAsset(this.portalTypeId);
    }
    
    public boolean exists() {
        return this.getPortalType() != null;
    }
    
    public int getTimeLimitSeconds() {
        return this.timeLimitSeconds;
    }
    
    public double getElapsedSeconds(final World world) {
        return this.worldRemovalCondition.getElapsedSeconds(world);
    }
    
    public double getRemainingSeconds(final World world) {
        return this.worldRemovalCondition.getRemainingSeconds(world);
    }
    
    public void setRemainingSeconds(final World world, final double seconds) {
        this.worldRemovalCondition.setRemainingSeconds(world, seconds);
    }
    
    public Set<UUID> getDiedInWorld() {
        return this.diedInWorld;
    }
    
    public Set<UUID> getSeesUi() {
        return this.seesUi;
    }
    
    public PortalGameplayConfig getGameplayConfig() {
        final GameplayConfig gameplayConfig = this.getPortalType().getGameplayConfig();
        final PortalGameplayConfig portalGameplayConfig = (gameplayConfig == null) ? null : gameplayConfig.getPluginConfig().get((Class<? extends PortalGameplayConfig>)PortalGameplayConfig.class);
        if (portalGameplayConfig != null) {
            return portalGameplayConfig;
        }
        return this.storedGameplayConfig;
    }
    
    public VoidEventConfig getVoidEventConfig() {
        return this.getGameplayConfig().getVoidEvent();
    }
    
    @Nullable
    public Transform getSpawnPoint() {
        return this.spawnPoint;
    }
    
    public void setSpawnPoint(final Transform spawnPoint) {
        this.spawnPoint = spawnPoint;
    }
    
    @Nullable
    public Ref<EntityStore> getVoidEventRef() {
        if (this.voidEventRef != null && !this.voidEventRef.isValid()) {
            this.voidEventRef = null;
        }
        return this.voidEventRef;
    }
    
    public boolean isVoidEventActive() {
        return this.getVoidEventRef() != null;
    }
    
    public void setVoidEventRef(final Ref<EntityStore> voidEventRef) {
        this.voidEventRef = voidEventRef;
    }
    
    public UpdatePortal createFullPacket(final World world) {
        final boolean hasBreach = this.getPortalType().isVoidInvasionEnabled();
        int breachSeconds;
        int explorationSeconds;
        if (hasBreach) {
            breachSeconds = this.getGameplayConfig().getVoidEvent().getDurationSeconds();
            explorationSeconds = this.timeLimitSeconds - breachSeconds;
        }
        else {
            explorationSeconds = this.timeLimitSeconds;
            breachSeconds = 0;
        }
        final PortalDef portalDef = new PortalDef(this.getPortalType().getDescription().getDisplayNameKey(), explorationSeconds, breachSeconds);
        return new UpdatePortal(this.createStateForPacket(world), portalDef);
    }
    
    public UpdatePortal createUpdatePacket(final World world) {
        return new UpdatePortal(this.createStateForPacket(world), null);
    }
    
    private PortalState createStateForPacket(final World world) {
        double remainingSeconds = this.worldRemovalCondition.getRemainingSeconds(world);
        final int breachSeconds = this.getGameplayConfig().getVoidEvent().getDurationSeconds();
        if (this.getPortalType().isVoidInvasionEnabled() && remainingSeconds > breachSeconds) {
            remainingSeconds -= breachSeconds;
        }
        return new PortalState((int)Math.ceil(remainingSeconds), this.isVoidEventActive());
    }
    
    @Override
    public Resource<EntityStore> clone() {
        final PortalWorld clone = new PortalWorld();
        clone.portalTypeId = this.portalTypeId;
        clone.timeLimitSeconds = this.timeLimitSeconds;
        clone.worldRemovalCondition = this.worldRemovalCondition;
        return clone;
    }
}
