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 dfl) {
        super.onScoreChanged(dfl);
        if (this.trackedObjectives.contains(dfl.getObjective())) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(Method.CHANGE, dfl.getObjective().getName(), dfl.getOwner(), dfl.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 dfj) {
        super.onPlayerScoreRemoved(string, dfj);
        if (this.trackedObjectives.contains(dfj)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetScorePacket(Method.REMOVE, dfj.getName(), string, 0));
        }
        this.setDirty();
    }
    
    @Override
    public void setDisplayObjective(final int integer, @Nullable final Objective dfj) {
        final Objective dfj2 = this.getDisplayObjective(integer);
        super.setDisplayObjective(integer, dfj);
        if (dfj2 != dfj && dfj2 != null) {
            if (this.getObjectiveDisplaySlotCount(dfj2) > 0) {
                this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(integer, dfj));
            }
            else {
                this.stopTrackingObjective(dfj2);
            }
        }
        if (dfj != null) {
            if (this.trackedObjectives.contains(dfj)) {
                this.server.getPlayerList().broadcastAll(new ClientboundSetDisplayObjectivePacket(integer, dfj));
            }
            else {
                this.startTrackingObjective(dfj);
            }
        }
        this.setDirty();
    }
    
    @Override
    public boolean addPlayerToTeam(final String string, final PlayerTeam dfk) {
        if (super.addPlayerToTeam(string, dfk)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(dfk, Arrays.<String>asList(string), 3));
            this.setDirty();
            return true;
        }
        return false;
    }
    
    @Override
    public void removePlayerFromTeam(final String string, final PlayerTeam dfk) {
        super.removePlayerFromTeam(string, dfk);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(dfk, Arrays.<String>asList(string), 4));
        this.setDirty();
    }
    
    @Override
    public void onObjectiveAdded(final Objective dfj) {
        super.onObjectiveAdded(dfj);
        this.setDirty();
    }
    
    @Override
    public void onObjectiveChanged(final Objective dfj) {
        super.onObjectiveChanged(dfj);
        if (this.trackedObjectives.contains(dfj)) {
            this.server.getPlayerList().broadcastAll(new ClientboundSetObjectivePacket(dfj, 2));
        }
        this.setDirty();
    }
    
    @Override
    public void onObjectiveRemoved(final Objective dfj) {
        super.onObjectiveRemoved(dfj);
        if (this.trackedObjectives.contains(dfj)) {
            this.stopTrackingObjective(dfj);
        }
        this.setDirty();
    }
    
    @Override
    public void onTeamAdded(final PlayerTeam dfk) {
        super.onTeamAdded(dfk);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(dfk, 0));
        this.setDirty();
    }
    
    @Override
    public void onTeamChanged(final PlayerTeam dfk) {
        super.onTeamChanged(dfk);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(dfk, 2));
        this.setDirty();
    }
    
    @Override
    public void onTeamRemoved(final PlayerTeam dfk) {
        super.onTeamRemoved(dfk);
        this.server.getPlayerList().broadcastAll(new ClientboundSetPlayerTeamPacket(dfk, 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 dfj) {
        final List<Packet<?>> list3 = Lists.newArrayList();
        list3.add(new ClientboundSetObjectivePacket(dfj, 0));
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == dfj) {
                list3.add(new ClientboundSetDisplayObjectivePacket(integer4, dfj));
            }
        }
        for (final Score dfl5 : this.getPlayerScores(dfj)) {
            list3.add(new ClientboundSetScorePacket(Method.CHANGE, dfl5.getObjective().getName(), dfl5.getOwner(), dfl5.getScore()));
        }
        return list3;
    }
    
    public void startTrackingObjective(final Objective dfj) {
        final List<Packet<?>> list3 = this.getStartTrackingPackets(dfj);
        for (final ServerPlayer ze5 : this.server.getPlayerList().getPlayers()) {
            for (final Packet<?> ni7 : list3) {
                ze5.connection.send(ni7);
            }
        }
        this.trackedObjectives.add(dfj);
    }
    
    public List<Packet<?>> getStopTrackingPackets(final Objective dfj) {
        final List<Packet<?>> list3 = Lists.newArrayList();
        list3.add(new ClientboundSetObjectivePacket(dfj, 1));
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == dfj) {
                list3.add(new ClientboundSetDisplayObjectivePacket(integer4, dfj));
            }
        }
        return list3;
    }
    
    public void stopTrackingObjective(final Objective dfj) {
        final List<Packet<?>> list3 = this.getStopTrackingPackets(dfj);
        for (final ServerPlayer ze5 : this.server.getPlayerList().getPlayers()) {
            for (final Packet<?> ni7 : list3) {
                ze5.connection.send(ni7);
            }
        }
        this.trackedObjectives.remove(dfj);
    }
    
    public int getObjectiveDisplaySlotCount(final Objective dfj) {
        int integer3 = 0;
        for (int integer4 = 0; integer4 < 19; ++integer4) {
            if (this.getDisplayObjective(integer4) == dfj) {
                ++integer3;
            }
        }
        return integer3;
    }
    
    public enum Method {
        CHANGE, 
        REMOVE;
    }
}
