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

package com.hypixel.hytale.server.core.entity.entities.player.windows;

import com.hypixel.hytale.event.IEvent;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Objects;
import com.hypixel.hytale.event.EventPriority;
import com.hypixel.hytale.event.EventRegistration;
import java.util.function.Consumer;
import com.hypixel.hytale.protocol.packets.window.WindowAction;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.google.gson.JsonObject;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import javax.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
import com.hypixel.hytale.event.SyncEventBusRegistry;
import javax.annotation.Nonnull;
import com.hypixel.hytale.logger.HytaleLogger;
import java.util.function.Supplier;
import com.hypixel.hytale.protocol.packets.window.WindowType;
import java.util.Map;

public abstract class Window
{
    public static final Map<WindowType, Supplier<? extends Window>> CLIENT_REQUESTABLE_WINDOW_TYPES;
    @Nonnull
    protected static final HytaleLogger LOGGER;
    @Nonnull
    protected final SyncEventBusRegistry<Void, WindowCloseEvent> closeEventRegistry;
    @Nonnull
    protected final WindowType windowType;
    @Nonnull
    protected final AtomicBoolean isDirty;
    @Nonnull
    protected final AtomicBoolean needRebuild;
    private int id;
    @Nullable
    private WindowManager manager;
    @Nullable
    private PlayerRef playerRef;
    
    public Window(@Nonnull final WindowType windowType) {
        this.closeEventRegistry = new SyncEventBusRegistry<Void, WindowCloseEvent>(Window.LOGGER, WindowCloseEvent.class);
        this.isDirty = new AtomicBoolean();
        this.needRebuild = new AtomicBoolean();
        this.windowType = windowType;
    }
    
    public void init(@Nonnull final PlayerRef playerRef, @Nonnull final WindowManager manager) {
        this.playerRef = playerRef;
        this.manager = manager;
    }
    
    @Nonnull
    public abstract JsonObject getData();
    
    protected boolean onOpen(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        return this.onOpen0(ref, store);
    }
    
    protected abstract boolean onOpen0(@Nonnull final Ref<EntityStore> p0, @Nonnull final Store<EntityStore> p1);
    
    protected void onClose(@Nonnull final Ref<EntityStore> ref, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        try {
            this.onClose0(ref, componentAccessor);
        }
        finally {
            this.closeEventRegistry.dispatchFor(null).dispatch(new WindowCloseEvent());
        }
    }
    
    protected abstract void onClose0(@Nonnull final Ref<EntityStore> p0, @Nonnull final ComponentAccessor<EntityStore> p1);
    
    public void handleAction(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final WindowAction action) {
    }
    
    @Nonnull
    public WindowType getType() {
        return this.windowType;
    }
    
    public void setId(final int id) {
        this.id = id;
    }
    
    public int getId() {
        return this.id;
    }
    
    @Nullable
    public PlayerRef getPlayerRef() {
        return this.playerRef;
    }
    
    public void close(@Nonnull final Ref<EntityStore> ref, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        assert this.manager != null;
        this.manager.closeWindow(ref, this.id, componentAccessor);
    }
    
    protected void invalidate() {
        this.isDirty.set(true);
    }
    
    protected void setNeedRebuild() {
        this.needRebuild.set(true);
        this.getData().addProperty("needRebuild", Boolean.TRUE);
    }
    
    protected boolean consumeIsDirty() {
        return this.isDirty.getAndSet(false);
    }
    
    protected void consumeNeedRebuild() {
        if (this.needRebuild.get()) {
            this.getData().remove("needRebuild");
            this.needRebuild.set(false);
        }
    }
    
    @Nonnull
    public EventRegistration registerCloseEvent(@Nonnull final Consumer<WindowCloseEvent> consumer) {
        return this.closeEventRegistry.register((short)0, null, consumer);
    }
    
    @Nonnull
    public EventRegistration registerCloseEvent(final short priority, @Nonnull final Consumer<WindowCloseEvent> consumer) {
        return this.closeEventRegistry.register(priority, null, consumer);
    }
    
    @Nonnull
    public EventRegistration registerCloseEvent(@Nonnull final EventPriority priority, @Nonnull final Consumer<WindowCloseEvent> consumer) {
        return this.closeEventRegistry.register(priority.getValue(), null, consumer);
    }
    
    @Override
    public boolean equals(@Nullable final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final Window window = (Window)o;
        return this.id == window.id && Objects.equals(this.windowType, window.windowType) && Objects.equals(this.playerRef, window.playerRef);
    }
    
    @Override
    public int hashCode() {
        int result = this.windowType.hashCode();
        result = 31 * result + this.id;
        result = 31 * result + ((this.playerRef != null) ? this.playerRef.hashCode() : 0);
        return result;
    }
    
    static {
        CLIENT_REQUESTABLE_WINDOW_TYPES = new ConcurrentHashMap<WindowType, Supplier<? extends Window>>();
        LOGGER = HytaleLogger.forEnclosingClass();
    }
    
    public static class WindowCloseEvent implements IEvent<Void>
    {
    }
}
