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

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

import com.hypixel.hytale.component.ArchetypeChunk;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.builtin.portals.components.PortalDeviceConfig;
import java.util.logging.Level;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.builtin.portals.utils.BlockTypeUtils;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.component.query.AndQuery;
import java.util.UUID;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.modules.block.BlockModule;
import com.hypixel.hytale.builtin.portals.components.PortalDevice;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.AddReason;
import javax.annotation.Nonnull;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.component.system.RefSystem;

public class PortalInvalidDestinationSystem extends RefSystem<ChunkStore>
{
    @Override
    public void onEntityAdded(@Nonnull final Ref<ChunkStore> ref, @Nonnull final AddReason reason, @Nonnull final Store<ChunkStore> store, @Nonnull final CommandBuffer<ChunkStore> commandBuffer) {
        if (reason != AddReason.LOAD) {
            return;
        }
        final World originWorld = store.getExternalData().getWorld();
        final PortalDevice portalDevice = commandBuffer.getComponent(ref, PortalDevice.getComponentType());
        final BlockModule.BlockStateInfo blockStateInfo = commandBuffer.getComponent(ref, BlockModule.BlockStateInfo.getComponentType());
        final World destinationWorld = portalDevice.getDestinationWorld();
        if (destinationWorld == null) {
            originWorld.execute(() -> turnOffPortalBlock(originWorld, portalDevice, blockStateInfo));
        }
    }
    
    @Override
    public void onEntityRemove(@Nonnull final Ref<ChunkStore> ref, @Nonnull final RemoveReason reason, @Nonnull final Store<ChunkStore> store, @Nonnull final CommandBuffer<ChunkStore> commandBuffer) {
    }
    
    @Override
    public Query<ChunkStore> getQuery() {
        return (Query<ChunkStore>)Query.and(PortalDevice.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
    }
    
    public static void turnOffPortalsInWorld(final World originWorld, final World destinationWorld) {
        final UUID destinationWorldUuid = destinationWorld.getWorldConfig().getUuid();
        final Store<ChunkStore> store = originWorld.getChunkStore().getStore();
        final AndQuery<ChunkStore> entityQuery = Query.and(PortalDevice.getComponentType(), BlockModule.BlockStateInfo.getComponentType());
        store.forEachEntityParallel(entityQuery, (id, archetypeChunk, commandBuffer) -> {
            final PortalDevice portalDevice = archetypeChunk.getComponent(id, PortalDevice.getComponentType());
            if (!(!destinationWorldUuid.equals(portalDevice.getDestinationWorldUuid()))) {
                final BlockModule.BlockStateInfo blockStateInfo = archetypeChunk.getComponent(id, BlockModule.BlockStateInfo.getComponentType());
                originWorld.execute(() -> turnOffPortalBlock(originWorld, portalDevice, blockStateInfo));
            }
        });
    }
    
    private static void turnOffPortalBlock(final World world, final PortalDevice portalDevice, final BlockModule.BlockStateInfo blockStateInfo) {
        final Ref<ChunkStore> chunkRef = blockStateInfo.getChunkRef();
        if (chunkRef == null || !chunkRef.isValid()) {
            return;
        }
        final Store<ChunkStore> store = world.getChunkStore().getStore();
        final WorldChunk worldChunk = store.getComponent(chunkRef, WorldChunk.getComponentType());
        if (worldChunk == null) {
            return;
        }
        final int index = blockStateInfo.getIndex();
        final int x = ChunkUtil.xFromBlockInColumn(index);
        final int y = ChunkUtil.yFromBlockInColumn(index);
        final int z = ChunkUtil.zFromBlockInColumn(index);
        final PortalDeviceConfig config = portalDevice.getConfig();
        final BlockType blockType = worldChunk.getBlockType(x, y, z);
        final BlockType offState = BlockTypeUtils.getBlockForState(blockType, config.getOffState());
        if (offState == null) {
            HytaleLogger.getLogger().at(Level.WARNING).log("Couldn't find/set off set for portal block, either " + blockType.getId() + " is misconfigured or the block changed unexpectedly");
            return;
        }
        worldChunk.setBlockInteractionState(x, y, z, blockType, config.getOffState(), false);
    }
}
