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

package com.hypixel.hytale.builtin.beds.sleep.systems.world;

import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ArchetypeChunk;
import java.util.Iterator;
import java.util.Collection;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import java.time.temporal.Temporal;
import java.time.Duration;
import com.hypixel.hytale.component.Ref;
import java.time.Instant;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSleep;
import com.hypixel.hytale.builtin.beds.sleep.components.PlayerSomnolence;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSleep;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSlumber;
import com.hypixel.hytale.builtin.beds.sleep.resources.WorldSomnolence;
import javax.annotation.Nonnull;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.system.tick.TickingSystem;

public class UpdateWorldSlumberSystem extends TickingSystem<EntityStore>
{
    static final /* synthetic */ boolean $assertionsDisabled;
    
    @Override
    public void tick(final float dt, final int systemIndex, @Nonnull final Store<EntityStore> store) {
        final World world = store.getExternalData().getWorld();
        final WorldSomnolence worldSomnolence = store.getResource(WorldSomnolence.getResourceType());
        final WorldSleep worldSleep = worldSomnolence.getState();
        if (!(worldSleep instanceof WorldSlumber)) {
            return;
        }
        final WorldSlumber slumber = (WorldSlumber)worldSleep;
        slumber.incProgressSeconds(dt);
        final boolean sleepingIsOver = slumber.getProgressSeconds() >= slumber.getIrlDurationSeconds() || isSomeoneAwake(store);
        if (!sleepingIsOver) {
            return;
        }
        worldSomnolence.setState(WorldSleep.Awake.INSTANCE);
        final WorldTimeResource timeResource = store.getResource(WorldTimeResource.getResourceType());
        final Instant wakeUpTime = computeWakeupTime(slumber);
        timeResource.setGameTime(wakeUpTime, world, store);
        store.forEachEntityParallel(PlayerSomnolence.getComponentType(), (index, archetypeChunk, commandBuffer) -> {
            final PlayerSomnolence somnolenceComponent = archetypeChunk.getComponent(index, PlayerSomnolence.getComponentType());
            if (!UpdateWorldSlumberSystem.$assertionsDisabled && somnolenceComponent == null) {
                throw new AssertionError();
            }
            else if (somnolenceComponent.getSleepState() instanceof PlayerSleep.Slumber) {
                final Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
                commandBuffer.putComponent(ref, PlayerSomnolence.getComponentType(), PlayerSleep.MorningWakeUp.createComponent(timeResource));
            }
        });
    }
    
    private static Instant computeWakeupTime(@Nonnull final WorldSlumber slumber) {
        final float progress = slumber.getProgressSeconds() / slumber.getIrlDurationSeconds();
        final long totalNanos = Duration.between(slumber.getStartInstant(), slumber.getTargetInstant()).toNanos();
        final long progressNanos = (long)(totalNanos * progress);
        return slumber.getStartInstant().plusNanos(progressNanos);
    }
    
    private static boolean isSomeoneAwake(@Nonnull final ComponentAccessor<EntityStore> store) {
        final World world = store.getExternalData().getWorld();
        final Collection<PlayerRef> playerRefs = world.getPlayerRefs();
        if (playerRefs.isEmpty()) {
            return false;
        }
        final Iterator<PlayerRef> iterator = playerRefs.iterator();
        if (!iterator.hasNext()) {
            return false;
        }
        final PlayerRef playerRef = iterator.next();
        final PlayerSomnolence somnolenceComponent = store.getComponent(playerRef.getReference(), PlayerSomnolence.getComponentType());
        if (somnolenceComponent == null) {
            return true;
        }
        final PlayerSleep sleepState = somnolenceComponent.getSleepState();
        return sleepState instanceof PlayerSleep.FullyAwake;
    }
}
