/FileExtraction/Java_unseen/Wind-Development_WindSpigot/WindSpigot-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
package org.bukkit.craftbukkit.scoreboard;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.Validate;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.util.WeakCollection;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.ScoreboardManager;

import net.minecraft.server.EntityPlayer;
import net.minecraft.server.IScoreboardCriteria;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PacketPlayOutScoreboardObjective;
import net.minecraft.server.PacketPlayOutScoreboardTeam;
import net.minecraft.server.Scoreboard;
import net.minecraft.server.ScoreboardObjective;
import net.minecraft.server.ScoreboardScore;
import net.minecraft.server.ScoreboardServer;
import net.minecraft.server.ScoreboardTeam;

public final class CraftScoreboardManager implements ScoreboardManager {
	private final CraftScoreboard mainScoreboard;
	private final MinecraftServer server;
	private final Collection<CraftScoreboard> scoreboards = new WeakCollection<CraftScoreboard>();
	private final Map<CraftPlayer, CraftScoreboard> playerBoards = new HashMap<CraftPlayer, CraftScoreboard>();

	public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.server.Scoreboard scoreboardServer) {
		mainScoreboard = new CraftScoreboard(scoreboardServer);
		server = minecraftserver;
		scoreboards.add(mainScoreboard);
	}

	@Override
	public CraftScoreboard getMainScoreboard() {
		return mainScoreboard;
	}

	@Override
	public CraftScoreboard getNewScoreboard() {
		org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot
		CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server));
		scoreboards.add(scoreboard);
		return scoreboard;
	}

	// CraftBukkit method
	public CraftScoreboard getPlayerBoard(CraftPlayer player) {
		CraftScoreboard board = playerBoards.get(player);
		return board == null ? getMainScoreboard() : board;
	}

	// CraftBukkit method
	public void setPlayerBoard(CraftPlayer player, org.bukkit.scoreboard.Scoreboard bukkitScoreboard)
			throws IllegalArgumentException {
		Validate.isTrue(bukkitScoreboard instanceof CraftScoreboard,
				"Cannot set player scoreboard to an unregistered Scoreboard");

		CraftScoreboard scoreboard = (CraftScoreboard) bukkitScoreboard;
		net.minecraft.server.Scoreboard oldboard = getPlayerBoard(player).getHandle();
		net.minecraft.server.Scoreboard newboard = scoreboard.getHandle();
		EntityPlayer entityplayer = player.getHandle();

		if (oldboard == newboard) {
			return;
		}

		if (scoreboard == mainScoreboard) {
			playerBoards.remove(player);
		} else {
			playerBoards.put(player, scoreboard);
		}

		// Old objective tracking
		HashSet<ScoreboardObjective> removed = new HashSet<ScoreboardObjective>();
		for (int i = 0; i < 3; ++i) {
			ScoreboardObjective scoreboardobjective = oldboard.getObjectiveForSlot(i);
			if (scoreboardobjective != null && !removed.contains(scoreboardobjective)) {
				entityplayer.playerConnection.sendPacket(new PacketPlayOutScoreboardObjective(scoreboardobjective, 1));
				removed.add(scoreboardobjective);
			}
		}

		// Old team tracking
		Iterator<?> iterator = oldboard.getTeams().iterator();
		while (iterator.hasNext()) {
			ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next();
			entityplayer.playerConnection.sendPacket(new PacketPlayOutScoreboardTeam(scoreboardteam, 1));
		}

		// The above is the reverse of the below method.
		server.getPlayerList().sendScoreboard((ScoreboardServer) newboard, player.getHandle());
	}

	// CraftBukkit method
	public void removePlayer(Player player) {
		playerBoards.remove(player);
	}

	// CraftBukkit method
	public Collection<ScoreboardScore> getScoreboardScores(IScoreboardCriteria criteria, String name,
			Collection<ScoreboardScore> collection) {
		for (CraftScoreboard scoreboard : scoreboards) {
			Scoreboard board = scoreboard.board;
			for (ScoreboardObjective objective : (Iterable<ScoreboardObjective>) board
					.getObjectivesForCriteria(criteria)) {
				collection.add(board.getPlayerScoreForObjective(name, objective));
			}
		}
		return collection;
	}

	// CraftBukkit method
	public void updateAllScoresForList(IScoreboardCriteria criteria, String name, List<EntityPlayer> of) {
		for (ScoreboardScore score : getScoreboardScores(criteria, name, new ArrayList<ScoreboardScore>())) {
			score.updateForList((List) of);
		}
	}
}
