package org.spacehq.mc.protocol.packet.ingame.server;

import org.spacehq.mc.auth.GameProfile;
import org.spacehq.mc.auth.properties.Property;
import org.spacehq.mc.protocol.data.game.values.MagicValues;
import org.spacehq.mc.protocol.data.game.values.PlayerListEntry;
import org.spacehq.mc.protocol.data.game.values.PlayerListEntryAction;
import org.spacehq.mc.protocol.data.game.values.entity.player.GameMode;
import org.spacehq.mc.protocol.data.message.Message;
import org.spacehq.packetlib.io.NetInput;
import org.spacehq.packetlib.io.NetOutput;
import org.spacehq.packetlib.packet.Packet;

import java.io.IOException;
import java.util.UUID;

public class ServerPlayerListEntryPacket implements Packet {
	private PlayerListEntryAction action;
	private PlayerListEntry entries[];

	@SuppressWarnings("unused")
	private ServerPlayerListEntryPacket() {
	}

	public ServerPlayerListEntryPacket(PlayerListEntryAction action, PlayerListEntry entries[]) {
		this.action = action;
		this.entries = entries;
	}

	public PlayerListEntryAction getAction() {
		return this.action;
	}

	public PlayerListEntry[] getEntries() {
		return this.entries;
	}

	@Override
	public void read(NetInput in) throws IOException {
		this.action = MagicValues.key(PlayerListEntryAction.class, in.readVarInt());
		this.entries = new PlayerListEntry[in.readVarInt()];
		for(int count = 0; count < this.entries.length; count++) {
			UUID uuid = in.readUUID();
			GameProfile profile;
			if(this.action == PlayerListEntryAction.ADD_PLAYER) {
				profile = new GameProfile(uuid, in.readString());
			} else {
				profile = new GameProfile(uuid, null);
			}

			PlayerListEntry entry = null;
			switch(this.action) {
				case ADD_PLAYER:
					int properties = in.readVarInt();
					for(int index = 0; index < properties; index++) {
						String propertyName = in.readString();
						String value = in.readString();
						String signature = null;
						if(in.readBoolean()) {
							signature = in.readString();
						}

						profile.getProperties().put(propertyName, new Property(propertyName, value, signature));
					}

					GameMode gameMode = MagicValues.key(GameMode.class, in.readVarInt());
					int ping = in.readVarInt();
					Message displayName = null;
					if(in.readBoolean()) {
						displayName = Message.fromString(in.readString());
					}

					entry = new PlayerListEntry(profile, gameMode, ping, displayName);
					break;
				case UPDATE_GAMEMODE:
					GameMode mode = MagicValues.key(GameMode.class, in.readVarInt());
					entry = new PlayerListEntry(profile, mode);
					break;
				case UPDATE_LATENCY:
					int png = in.readVarInt();
					entry = new PlayerListEntry(profile, png);
					break;
				case UPDATE_DISPLAY_NAME:
					Message disp = null;
					if(in.readBoolean()) {
						disp = Message.fromString(in.readString());
					}

					entry = new PlayerListEntry(profile, disp);
				case REMOVE_PLAYER:
					entry = new PlayerListEntry(profile);
					break;
			}

			this.entries[count] = entry;
		}
	}

	@Override
	public void write(NetOutput out) throws IOException {
		out.writeVarInt(MagicValues.value(Integer.class, this.action));
		out.writeVarInt(this.entries.length);
		for(PlayerListEntry entry : this.entries) {
			out.writeUUID(entry.getProfile().getId());
			switch(this.action) {
				case ADD_PLAYER:
					out.writeString(entry.getProfile().getName());
					out.writeVarInt(entry.getProfile().getProperties().size());
					for(Property property : entry.getProfile().getProperties().values()) {
						out.writeString(property.getName());
						out.writeString(property.getValue());
						out.writeBoolean(property.hasSignature());
						if(property.hasSignature()) {
							out.writeString(property.getSignature());
						}
					}

					out.writeVarInt(MagicValues.value(Integer.class, entry.getGameMode()));
					out.writeVarInt(entry.getPing());
					break;
				case UPDATE_GAMEMODE:
					out.writeVarInt(MagicValues.value(Integer.class, entry.getGameMode()));
					break;
				case UPDATE_LATENCY:
					out.writeVarInt(entry.getPing());
					break;
				case REMOVE_PLAYER:
					break;
			}
		}
	}

	@Override
	public boolean isPriority() {
		return false;
	}
}

@@ -3843,32 +3843,199 @@
 try.getPing());%0A
+%09%09%09%09%09out.writeBoolean(entry.getDisplayName() != null);%0A%09%09%09%09%09if(entry.getDisplayName() != null) %7B%0A%09%09%09%09%09%09out.writeString(entry.getDisplayName().toJsonString());%0A%09%09%09%09%09%7D%0A%0A
 %09%09%09%09%09break;%0A%09%09%09%09
@@ -4205,24 +4205,233 @@
 getPing());%0A
+%09%09%09%09%09break;%0A%09%09%09%09case UPDATE_DISPLAY_NAME:%0A%09%09%09%09%09out.writeBoolean(entry.getDisplayName() != null);%0A%09%09%09%09%09if(entry.getDisplayName() != null) %7B%0A%09%09%09%09%09%09out.writeString(entry.getDisplayName().toJsonString());%0A%09%09%09%09%09%7D%0A%0A
 %09%09%09%09%09break;%0A

Add missing code for writing display name data in ServerPlayerListEntryPacket.