package server;
import java.util.LinkedList;
import java.util.List;
import clientside.MapleCharacter;
import handling.channel.ChannelServer;
import handling.world.World;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ScheduledFuture;
import server.Timer.EtcTimer;
import server.maps.MapleMap;
import tools.packet.CField;
import tools.Pair;
import tools.packet.CWvsContext;
public class MapleSquad {
public static enum MapleSquadType {
bossbalrog(2), zak(2), hilla(1), arkarium(2), chaoszak(3), queen(2), horntail(2), chaosht(3), pinkbean(3), nmm_squad(2), vergamot(2), dunas(2), nibergen_squad(2), dunas2(2), core_blaze(2), aufheben(2), cwkpq(10), tokyo_2095(2), vonleon(3), scartar(2), cygnus(3);
private MapleSquadType(int i) {
this.i = i;
}
public int i;
public HashMap<Integer, ArrayList<Pair<String, String>>> queuedPlayers = new HashMap<Integer, ArrayList<Pair<String, String>>>();
public HashMap<Integer, ArrayList<Pair<String, Long>>> queue = new HashMap<Integer, ArrayList<Pair<String, Long>>>();
}
private WeakReference<MapleCharacter> leader;
private final String leaderName, toSay;
private final Map<String, String> members = new LinkedHashMap<String, String>();
private final Map<String, String> bannedMembers = new LinkedHashMap<String, String>();
private final int ch;
private final long startTime;
private final int expiration;
private final int beginMapId;
private final MapleSquadType type;
private byte status = 0;
private ScheduledFuture<?> removal;
public MapleSquad(final int ch, final String type, final MapleCharacter leader, final int expiration, final String toSay) {
this.leader = new WeakReference<MapleCharacter>(leader);
this.members.put(leader.getName(), MapleCarnivalChallenge.getJobBasicNameById(leader.getJob()));
this.leaderName = leader.getName();
this.ch = ch;
this.toSay = toSay;
this.type = MapleSquadType.valueOf(type.toLowerCase());
this.status = 1;
this.beginMapId = leader.getMapId();
leader.getMap().setSquad(this.type);
if (this.type.queue.get(ch) == null) {
this.type.queue.put(ch, new ArrayList<Pair<String, Long>>());
this.type.queuedPlayers.put(ch, new ArrayList<Pair<String, String>>());
}
this.startTime = System.currentTimeMillis();
this.expiration = expiration;
}
public void copy() {
while (type.queue.get(ch).size() > 0 && ChannelServer.getInstance(ch).getMapleSquad(type) == null) {
int index = 0;
long lowest = 0;
for (int i = 0; i < type.queue.get(ch).size(); i++) {
if (lowest == 0 || type.queue.get(ch).get(i).right < lowest) {
index = i;
lowest = type.queue.get(ch).get(i).right;
}
}
final String nextPlayerId = type.queue.get(ch).remove(index).left;
final int theirCh = World.Find.findChannel(nextPlayerId);
if (theirCh > 0) {
final MapleCharacter lead = ChannelServer.getInstance(theirCh).getPlayerStorage().getCharacterByName(nextPlayerId);
if (lead != null && lead.getMapId() == beginMapId && lead.getClient().getChannel() == ch) {
final MapleSquad squad = new MapleSquad(ch, type.name(), lead, expiration, toSay);
if (ChannelServer.getInstance(ch).addMapleSquad(squad, type.name())) {
getBeginMap().broadcastMessage(CField.getClock(expiration / 1000));
getBeginMap().broadcastMessage(CWvsContext.serverNotice(6, nextPlayerId + toSay));
type.queuedPlayers.get(ch).add(new Pair<String, String>(nextPlayerId, "Success"));
} else {
squad.clear();
type.queuedPlayers.get(ch).add(new Pair<String, String>(nextPlayerId, "Skipped"));
}
break;
} else {
if (lead != null) {
lead.dropMessage(6, "Your squad has been skipped due to you not being in the right channel and map.");
}
getBeginMap().broadcastMessage(CWvsContext.serverNotice(6, nextPlayerId + "'s squad has been skipped due to the player not being in the right channel and map."));
type.queuedPlayers.get(ch).add(new Pair<String, String>(nextPlayerId, "Not in map"));
}
} else {
getBeginMap().broadcastMessage(CWvsContext.serverNotice(6, nextPlayerId + "'s squad has been skipped due to the player not being online."));
type.queuedPlayers.get(ch).add(new Pair<String, String>(nextPlayerId, "Not online"));
}
}
}
public MapleMap getBeginMap() {
return ChannelServer.getInstance(ch).getMapFactory().getMap(beginMapId);
}
public void clear() {
if (removal != null) {
getBeginMap().broadcastMessage(CField.stopClock());
removal.cancel(false);
removal = null;
}
members.clear();
bannedMembers.clear();
leader = null;
ChannelServer.getInstance(ch).removeMapleSquad(type);
this.status = 0;
}
public MapleCharacter getChar(String name) {
return ChannelServer.getInstance(ch).getPlayerStorage().getCharacterByName(name);
}
public long getTimeLeft() {
return expiration - (System.currentTimeMillis() - startTime);
}
public void scheduleRemoval() {
removal = EtcTimer.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (status != 0 && leader != null && (getLeader() == null || status == 1)) { //leader itself = null means we're already cleared
clear();
copy();
}
}
}, expiration);
}
public String getLeaderName() {
return leaderName;
}
public List<Pair<String, Long>> getAllNextPlayer() {
return type.queue.get(ch);
}
public String getNextPlayer() {
StringBuilder sb = new StringBuilder("\nQueued members : ");
sb.append("#b").append(type.queue.get(ch).size()).append(" #k ").append("List of participants : \n\r ");
int i = 0;
for (Pair<String, Long> chr : type.queue.get(ch)) {
i++;
sb.append(i).append(" : ").append(chr.left);
sb.append(" \n\r ");
}
sb.append("Would you like to #ebe next#n in the queue, or #ebe removed#n from the queue if you are in it?");
return sb.toString();
}
public void setNextPlayer(String i) {
Pair<String, Long> toRemove = null;
for (Pair<String, Long> s : type.queue.get(ch)) {
if (s.left.equals(i)) {
toRemove = s;
break;
}
}
if (toRemove != null) {
type.queue.get(ch).remove(toRemove);
return;
}
for (ArrayList<Pair<String, Long>> v : type.queue.values()) {
for (Pair<String, Long> s : v) {
if (s.left.equals(i)) {
return;
}
}
}
type.queue.get(ch).add(new Pair<String, Long>(i, System.currentTimeMillis()));
}
public MapleCharacter getLeader() {
if (leader == null || leader.get() == null) {
if (members.size() > 0 && getChar(leaderName) != null) {
leader = new WeakReference<MapleCharacter>(getChar(leaderName));
} else {
if (status != 0) {
clear();
}
return null;
}
}
return leader.get();
}
public boolean containsMember(MapleCharacter member) {
for (String mmbr : members.keySet()) {
if (mmbr.equalsIgnoreCase(member.getName())) {
return true;
}
}
return false;
}
public List<String> getMembers() {
return new LinkedList<String>(members.keySet());
}
public List<String> getBannedMembers() {
return new LinkedList<String>(bannedMembers.keySet());
}
public int getSquadSize() {
return members.size();
}
public boolean isBanned(MapleCharacter member) {
return bannedMembers.containsKey(member.getName());
}
public int addMember(MapleCharacter member, boolean join) {
if (getLeader() == null) {
return -1;
}
final String job = MapleCarnivalChallenge.getJobBasicNameById(member.getJob());
if (join) {
if (!containsMember(member) && !getAllNextPlayer().contains(member.getName())) {
if (members.size() <= 30) {
members.put(member.getName(), job);
getLeader().dropMessage(5, member.getName() + " (" + job + ") has joined the fight!");
return 1;
}
return 2;
}
return -1;
} else {
if (containsMember(member)) {
members.remove(member.getName());
getLeader().dropMessage(5, member.getName() + " (" + job + ") have withdrawed from the fight.");
return 1;
}
return -1;
}
}
public void acceptMember(int pos) {
if (pos < 0 || pos >= bannedMembers.size()) {
return;
}
final List<String> membersAsList = getBannedMembers();
final String toadd = membersAsList.get(pos);
if (toadd != null && getChar(toadd) != null) {
members.put(toadd, bannedMembers.get(toadd));
bannedMembers.remove(toadd);
getChar(toadd).dropMessage(5, getLeaderName() + " has decided to add you back to the squad.");
}
}
public void reAddMember(MapleCharacter chr) {
removeMember(chr);
members.put(chr.getName(), MapleCarnivalChallenge.getJobBasicNameById(chr.getJob()));
}
public void removeMember(MapleCharacter chr) {
if (members.containsKey(chr.getName())) {
members.remove(chr.getName());
}
}
public void removeMember(String chr) {
if (members.containsKey(chr)) {
members.remove(chr);
}
}
public void banMember(int pos) {
if (pos <= 0 || pos >= members.size()) { //may not ban leader
return;
}
final List<String> membersAsList = getMembers();
final String toban = membersAsList.get(pos);
if (toban != null && getChar(toban) != null) {
bannedMembers.put(toban, members.get(toban));
members.remove(toban);
getChar(toban).dropMessage(5, getLeaderName() + " has removed you from the squad.");
}
}
public void setStatus(byte status) {
this.status = status;
if (status == 2 && removal != null) {
removal.cancel(false);
removal = null;
}
}
public int getStatus() {
return status;
}
public int getBannedMemberSize() {
return bannedMembers.size();
}
public String getSquadMemberString(byte type) {
switch (type) {
case 0: {
StringBuilder sb = new StringBuilder("Squad members : ");
sb.append("#b").append(members.size()).append(" #k ").append("List of participants : \n\r ");
int i = 0;
for (Entry<String, String> chr : members.entrySet()) {
i++;
sb.append(i).append(" : ").append(chr.getKey()).append(" (").append(chr.getValue()).append(") ");
if (i == 1) {
sb.append("(Leader of the squad)");
}
sb.append(" \n\r ");
}
while (i < 30) {
i++;
sb.append(i).append(" : ").append(" \n\r ");
}
return sb.toString();
}
case 1: {
StringBuilder sb = new StringBuilder("Squad members : ");
sb.append("#b").append(members.size()).append(" #n ").append("List of participants : \n\r ");
int i = 0, selection = 0;
for (Entry<String, String> chr : members.entrySet()) {
i++;
sb.append("#b#L").append(selection).append("#");
selection++;
sb.append(i).append(" : ").append(chr.getKey()).append(" (").append(chr.getValue()).append(") ");
if (i == 1) {
sb.append("(Leader of the squad)");
}
sb.append("#l").append(" \n\r ");
}
while (i < 30) {
i++;
sb.append(i).append(" : ").append(" \n\r ");
}
return sb.toString();
}
case 2: {
StringBuilder sb = new StringBuilder("Squad members : ");
sb.append("#b").append(members.size()).append(" #n ").append("List of participants : \n\r ");
int i = 0, selection = 0;
for (Entry<String, String> chr : bannedMembers.entrySet()) {
i++;
sb.append("#b#L").append(selection).append("#");
selection++;
sb.append(i).append(" : ").append(chr.getKey()).append(" (").append(chr.getValue()).append(") ");
sb.append("#l").append(" \n\r ");
}
while (i < 30) {
i++;
sb.append(i).append(" : ").append(" \n\r ");
}
return sb.toString();
}
case 3: { //CWKPQ
StringBuilder sb = new StringBuilder("Jobs : ");
final Map<String, Integer> jobs = getJobs();
for (Entry<String, Integer> chr : jobs.entrySet()) {
sb.append("\r\n").append(chr.getKey()).append(" : ").append(chr.getValue());
}
return sb.toString();
}
}
return null;
}
public final MapleSquadType getType() {
return type;
}
public final Map<String, Integer> getJobs() {
final Map<String, Integer> jobs = new LinkedHashMap<String, Integer>();
for (Entry<String, String> chr : members.entrySet()) {
if (jobs.containsKey(chr.getValue())) {
jobs.put(chr.getValue(), jobs.get(chr.getValue()) + 1);
} else {
jobs.put(chr.getValue(), 1);
}
}
return jobs;
}
}