package net.minecraft.server;

import net.minecraft.server.level.ServerPlayer;
import java.util.Iterator;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.network.protocol.game.ClientboundSetObjectivePacket;
import java.util.Collection;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import java.util.Arrays;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.network.protocol.game.ClientboundSetDisplayObjectivePacket;
import javax.annotation.Nullable;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundSetScorePacket;
import net.minecraft.world.scores.Score;
import com.google.common.collect.Sets;
import net.minecraft.world.scores.Objective;
import java.util.Set;
import net.minecraft.world.scores.Scoreboard;

public class ServerScoreboard extends Scoreboard {
    private final MinecraftServer server;
    private final Set<Objective> trackedObjectives;
    private Runnable[] dirtyListeners;
    
    public ServerScoreboard(final MinecraftServer minecraftServer) {
        this.trackedObjectives = Sets.newHashSet();
        this.dirtyListeners = new Runnable[0];
        this.server = minecraftServer;
    }
    
    @Override
    public void onScoreChanged(final Score cwk) {
        super.onScoreChanged(cwk);
        if (this.trackedObjectives.contains(cwk.getObjective())) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(Method.CHANGE, cwk.getObjective().getName(), cwk.getOwner(), cwk.getScore()));
        }
        this.setDirty();
    }
    
    @Override
    public void onPlayerRemoved(final String string) {
        super.onPlayerRemoved(string);
        this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(Method.REMOVE, null, string, 0));
        this.setDirty();
    }
    
    @Override
    public void onPlayerScoreRemoved(final String string, final Objective cwi) {
        super.onPlayerScoreRemoved(string, cwi);
        if (this.trackedObjectives.contains(cwi)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(Method.REMOVE, cwi.getName(), string, 0));
        }
        this.setDirty();
    }
    
    @Override
    public void setDisplayObjective(final int integer, @Nullable final Objective cwi) {
        final Objective cwi2 = this.getDisplayObjective(integer);
        super.setDisplayObjective(integer, cwi);
        if (cwi2 != cwi && cwi2 != null) {
            if (this.getObjectiveDisplaySlotCount(cwi2) > 0) {
                this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(integer, cwi));
            }
            else {
                this.stopTrackingObjective(cwi2);
            }
        }
        if (cwi != null) {
            if (this.trackedObjectives.contains(cwi)) {
                this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(integer, cwi));
            }
            else {
                this.startTrackingObjective(cwi);
            }
        }
        this.setDirty();
    }
    
    @Override
    public boolean addPlayerToTeam(final String string, final PlayerTeam cwj) {
        if (super.addPlayerToTeam(string, cwj)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(cwj, Arrays.<String>asList(string), 3));
            this.setDirty();
            return true;
        }
        return false;
    }
    
    @Override
    public void removePlayerFromTeam(final String string, final PlayerTeam cwj) {
        super.removePlayerFromTeam(string, cwj);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(cwj, Arrays.<String>asList(string), 4));
        this.setDirty();
    }
    
    @Override
    public void onObjectiveAdded(final Objective cwi) {
        super.onObjectiveAdded(cwi);
        this.setDirty();
    }
    
    @Override
    public void onObjectiveChanged(final Objective cwi) {
        super.onObjectiveChanged(cwi);
        if (this.trackedObjectives.contains(cwi)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(cwi, 2));
        }
        this.setDirty();
    }
    
    @Override
    public void onObjectiveRemoved(final Objective cwi) {
        super.onObjectiveRemoved(cwi);
        if (this.trackedObjectives.contains(cwi)) {
            this.stopTrackingObjective(cwi);
        }
        this.setDirty();
    }
    
    @Override
    public void onTeamAdded(final PlayerTeam cwj) {
        super.onTeamAdded(cwj);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(cwj, 0));
        this.setDirty();
    }
    
    @Override
    public void onTeamChanged(final PlayerTeam cwj) {
        super.onTeamChanged(cwj);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(cwj, 2));
        this.setDirty();
    }
    
    @Override
    public void onTeamRemoved(final PlayerTeam cwj) {
        super.onTeamRemoved(cwj);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(cwj, 1));
        this.setDirty();
    }
    
    public void addDirtyListener(final Runnable runnable) {
        (this.dirtyListeners = Arrays.<Runnable>copyOf(this.dirtyListeners, this.dirtyListeners.length + 1))[this.dirtyListeners.length - 1] = runnable;
    }
    
    protected void setDirty() {
        for (final Runnable runnable5 : this.dirtyListeners) {
            runnable5.run();
        }
    }
    
    public List<Packet<?>> getStartTrackingPackets(final Objective cwi) {
        final List<Packet<?>> list3 = Lists.newArrayList();
        list3.add(new ClientboundSetObjectivePacket(cwi, 0));
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == cwi) {
                list3.add(new ClientboundSetDisplayObjectivePacket(integer4, cwi));
            }
        }
        for (final Score cwk5 : this.getPlayerScores(cwi)) {
            list3.add(new ClientboundSetScorePacket(Method.CHANGE, cwk5.getObjective().getName(), cwk5.getOwner(), cwk5.getScore()));
        }
        return list3;
    }
    
    public void startTrackingObjective(final Objective cwi) {
        final List<Packet<?>> list3 = this.getStartTrackingPackets(cwi);
        for (final ServerPlayer xe5 : this.server.getPlayerList().getPlayers()) {
            for (final Packet<?> lt7 : list3) {
                xe5.connection.send(lt7);
            }
        }
        this.trackedObjectives.add(cwi);
    }
    
    public List<Packet<?>> getStopTrackingPackets(final Objective cwi) {
        final List<Packet<?>> list3 = Lists.newArrayList();
        list3.add(new ClientboundSetObjectivePacket(cwi, 1));
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == cwi) {
                list3.add(new ClientboundSetDisplayObjectivePacket(integer4, cwi));
            }
        }
        return list3;
    }
    
    public void stopTrackingObjective(final Objective cwi) {
        final List<Packet<?>> list3 = this.getStopTrackingPackets(cwi);
        for (final ServerPlayer xe5 : this.server.getPlayerList().getPlayers()) {
            for (final Packet<?> lt7 : list3) {
                xe5.connection.send(lt7);
            }
        }
        this.trackedObjectives.remove(cwi);
    }
    
    public int getObjectiveDisplaySlotCount(final Objective cwi) {
        int integer3 = 0;
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == cwi) {
                ++integer3;
            }
        }
        return integer3;
    }
    
    public enum Method {
        CHANGE, 
        REMOVE;
    }
}
