/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jserver.gameserver.model.olympiad;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import com.l2jserver.Config;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.zone.type.L2OlympiadStadiumZone;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExOlympiadUserInfo;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;

/**
 * @author Pere, DS
 */
public class OlympiadGameTeams extends AbstractOlympiadGame
{
	public static final int MAX_TEAM_SIZE = 3;

	protected boolean _teamOneDefaulted;
	protected boolean _teamTwoDefaulted;
	
	protected int _damageT1 = 0;
	protected int _damageT2 = 0;

	protected final int _teamOneSize;
	protected final int _teamTwoSize;
	protected final Participant[] _teamOne;
	protected final Participant[] _teamTwo;

	protected OlympiadGameTeams(int id, Participant[] teamOne, Participant[] teamTwo)
	{
		super(id);

		_teamOneSize = Math.min(teamOne.length, MAX_TEAM_SIZE);
		_teamTwoSize = Math.min(teamTwo.length, MAX_TEAM_SIZE);
		_teamOne = new Participant[MAX_TEAM_SIZE];
		_teamTwo = new Participant[MAX_TEAM_SIZE];

		Participant par;
		for (int i = 0; i < MAX_TEAM_SIZE; i++)
		{
			if (i < _teamOneSize)
			{
				par = teamOne[i];
				_teamOne[i] = par;
				if (par.getPlayer() != null)
					par.getPlayer().setOlympiadGameId(id);
			}
			else
				_teamOne[i] = new Participant(IdFactory.getInstance().getNextId(), 1);

			if (i < _teamTwoSize)
			{
				par = teamTwo[i];
				_teamTwo[i] = par;
				if (par.getPlayer() != null)
					par.getPlayer().setOlympiadGameId(id);
			}
			else
				_teamTwo[i] = new Participant(IdFactory.getInstance().getNextId(), 2);
		}
	}
	
	protected static final Participant[][] createListOfParticipants(List<List<Integer>> list)
	{
		if (list == null || list.isEmpty() || list.size() < 2)
			return null;

		List<Integer> teamOne = null;
		List<Integer> teamTwo = null;
		L2PcInstance player;
		List<L2PcInstance> teamOnePlayers = new ArrayList<>(MAX_TEAM_SIZE);
		List<L2PcInstance> teamTwoPlayers = new ArrayList<>(MAX_TEAM_SIZE);

		while (list.size() > 1)
		{
			teamOne = list.remove(Rnd.nextInt(list.size()));

			if ((teamOne == null || teamOne.isEmpty()))
				continue;

			for (int objectId : teamOne)
			{
				player = L2World.getInstance().getPlayer(objectId);
				if (player == null || !player.isOnline())
				{
					teamOnePlayers.clear();
					break;
				}
				teamOnePlayers.add(player);
			}
			if (teamOnePlayers.isEmpty())
				continue;

			teamTwo = list.remove(Rnd.nextInt(list.size()));
			if (teamTwo == null || teamTwo.isEmpty())
			{
				list.add(teamOne);
				teamOnePlayers.clear();
				continue;
			}

			for (int objectId : teamTwo)
			{
				player = L2World.getInstance().getPlayer(objectId);
				if (player == null || !player.isOnline())
				{
					teamTwoPlayers.clear();
					break;
				}
				teamTwoPlayers.add(player);
			}
			if (teamTwoPlayers.isEmpty())
			{
				list.add(teamOne);
				teamOnePlayers.clear();
				continue;
			}

			Participant[] t1 = new Participant[teamOnePlayers.size()];
			Participant[] t2 = new Participant[teamTwoPlayers.size()];
			Participant[][] result = new Participant[2][];

			for (int i = 0; i < t1.length; i++)
				t1[i] = new Participant(teamOnePlayers.get(i), 1);

			for (int i = 0; i < t2.length; i++)
				t2[i] = new Participant(teamTwoPlayers.get(i), 2);

			result[0] = t1;
			result[1] = t2;
			return result;
		}

		return null;
	}

	protected static OlympiadGameTeams createGame(int id, List<List<Integer>> list)
	{
		final Participant[][] teams = createListOfParticipants(list);
		if (teams == null)
			return null;

		return new OlympiadGameTeams(id, teams[0], teams[1]);
	}

	@Override
	public CompetitionType getType()
	{
		return CompetitionType.TEAMS;
	}

	@Override
	protected int getDivider()
	{
		return 5;
	}

	@Override
	protected int[][] getReward()
	{
		return Config.ALT_OLY_TEAM_REWARD;
	}
	
	@Override
	protected final String getWeeklyMatchType()
	{
		return COMP_DONE_WEEK_TEAM;
	}

	@Override
	public final boolean containsParticipant(int playerId)
	{
		for (int i = _teamOneSize; --i >= 0;)
		{
			if (_teamOne[i].getObjectId() == playerId)
				return true;
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			if (_teamTwo[i].getObjectId() == playerId)
				return true;
		}
		return false;
	}

	@Override
	public final void sendOlympiadInfo(L2Character player)
	{
		for (int i = 0; i < MAX_TEAM_SIZE; i++)
			player.sendPacket(new ExOlympiadUserInfo(_teamOne[i]));

		for (int i = 0; i < MAX_TEAM_SIZE; i++)
			player.sendPacket(new ExOlympiadUserInfo(_teamTwo[i]));
	}

	@Override
	public final void broadcastOlympiadInfo(L2OlympiadStadiumZone stadium)
	{
		for (int i = 0; i < MAX_TEAM_SIZE; i++)
			stadium.broadcastPacket(new ExOlympiadUserInfo(_teamOne[i]));

		for (int i = 0; i < MAX_TEAM_SIZE; i++)
			stadium.broadcastPacket(new ExOlympiadUserInfo(_teamTwo[i]));
	}

	@Override
	protected final void broadcastPacket(L2GameServerPacket packet)
	{
		Participant par;
		for (int i = 0; i < _teamOneSize; i++)
		{
			par = _teamOne[i];
			if (par.updatePlayer())
			{
				par.getPlayer().sendPacket(packet);
			}
		}

		for (int i = 0; i < _teamTwoSize; i++)
		{
			par = _teamTwo[i];
			par.
			updatePlayer();
			if (par.getPlayer() != null)
				par.getPlayer().sendPacket(packet);
		}
	}

	@Override
	protected boolean needBuffers()
	{
		return false;
	}

	@Override
	protected final boolean portPlayersToArena(List<Location> spawns)
	{
		boolean result = true;
		try
		{
			for (int i = 0; i < _teamOneSize; i++)
				result &= portPlayerToArena(_teamOne[i], spawns.get(i), _stadiumID);

			final int offset = spawns.size() / 2;
			for (int i = 0; i < _teamTwoSize; i++)
				result &= portPlayerToArena(_teamTwo[i], spawns.get(i + offset), _stadiumID);
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "", e);
			return false;
		}
		return result;
	}

	@Override
	protected final void removals()
	{
		for (int i = _teamOneSize; --i >= 0;)
			removals(_teamOne[i].getPlayer(), false);

		for (int i = _teamTwoSize; --i >= 0;)
			removals(_teamTwo[i].getPlayer(), false);
	}

	@Override
	protected final boolean makeCompetitionStart()
	{
		if (!super.makeCompetitionStart())
			return false;

		Participant par;
		for (int i = 0; i < _teamOneSize; i++)
		{
			par = _teamOne[i];
			if (par.getPlayer() == null)
				return false;

			par.getPlayer().setIsOlympiadStart(true);
			par.getPlayer().updateEffectIcons();
		}

		for (int i = 0; i < _teamTwoSize; i++)
		{
			par = _teamTwo[i];
			if (par.getPlayer() == null)
				return false;

			par.getPlayer().setIsOlympiadStart(true);
			par.getPlayer().updateEffectIcons();
		}
		return true;
	}

	@Override
	protected final void cleanEffects()
	{
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected()
					&& par.getPlayer().getOlympiadGameId() == _stadiumID)
				cleanEffects(par.getPlayer());
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected()
					&& par.getPlayer().getOlympiadGameId() == _stadiumID)
				cleanEffects(par.getPlayer());
		}
	}

	@Override
	protected final void portPlayersBack()
	{
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected())
				portPlayerBack(par.getPlayer());
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected())
				portPlayerBack(par.getPlayer());
		}
	}

	@Override
	protected final void playersStatusBack()
	{
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected()
					&& par.getPlayer().getOlympiadGameId() == _stadiumID)
				playerStatusBack(par.getPlayer());
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (par.getPlayer() != null
					&& !par.isDefaulted()
					&& !par.isDisconnected()
					&& par.getPlayer().getOlympiadGameId() == _stadiumID)
				playerStatusBack(par.getPlayer());
		}
	}

	@Override
	protected final void clearPlayers()
	{
		for (int i = 0; i < MAX_TEAM_SIZE; i++)
		{
			if (i < _teamOneSize)
				_teamOne[i].setPlayer(null);
			else
				IdFactory.getInstance().releaseId(_teamOne[i].getObjectId());

			if (i < _teamTwoSize)
				_teamTwo[i].setPlayer(null);
			else
				IdFactory.getInstance().releaseId(_teamTwo[i].getObjectId());

			_teamOne[i] = null;
			_teamTwo[i] = null;
		}
	}
	
	@Override
	protected final void handleDisconnect(L2PcInstance player)
	{
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (par.getObjectId() == player.getObjectId())
			{
				par.setDisconnected(true);
				return;
			}
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (par.getObjectId() == player.getObjectId())
			{
				par.setDisconnected(true);
				return;
			}
		}
	}
	
	@Override
	protected final boolean haveWinner()
	{
		if (!checkBattleStatus())
			return true;
		
		boolean teamOneLost = true;
		boolean teamTwoLost = true;
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (!par.isDisconnected())
			{
				if (par.getPlayer() != null && par.getPlayer().getOlympiadGameId() == _stadiumID)
					teamOneLost &= par.getPlayer().isDead();
			}
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (!par.isDisconnected())
			{
				if (par.getPlayer() != null && par.getPlayer().getOlympiadGameId() == _stadiumID)
					teamTwoLost &= par.getPlayer().isDead();
			}
		}
		
		return teamOneLost || teamTwoLost;
	}
	
	@Override
	protected final boolean checkBattleStatus()
	{
		if (_aborted)
			return false;		

		if (teamOneAllDisconnected())
			return false;

		if (teamTwoAllDisconnected())
			return false;

		return true;
	}

	@Override
	protected void validateWinner(L2OlympiadStadiumZone stadium)
	{
		if (_aborted)
			return;
		
		final boolean tOneCrash = teamOneAllDisconnected();
		final boolean tTwoCrash = teamTwoAllDisconnected();
		
		Participant par;
		SystemMessage sm;
		int points;

		// Check for if a team defaulted before battle started
		if (_teamOneDefaulted || _teamTwoDefaulted)
		{
			try
			{
				if (_teamOneDefaulted)
				{
					for (int i = _teamOneSize; --i >= 0;)
					{
						par = _teamOne[i];
						removePointsFromParticipant(par, Math.min(par.getStats().getInteger(POINTS) / 3, Config.ALT_OLY_MAX_POINTS));
					}
				}
				if (_teamTwoDefaulted)
				{
					for (int i = _teamTwoSize; --i >= 0;)
					{
						par = _teamTwo[i];
						removePointsFromParticipant(par, Math.min(par.getStats().getInteger(POINTS) / 3, Config.ALT_OLY_MAX_POINTS));
					}
				}
			}
			catch (Exception e)
			{
				_log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
			}
			return;
		}
		
		 // points to be dedicted in case of losing
		final int[] pointsTeamOne = new int[_teamOneSize];
		final int[] pointsTeamTwo = new int[_teamTwoSize];
		final int[] maxPointsTeamOne = new int[_teamOneSize];
		final int[] maxPointsTeamTwo = new int[_teamTwoSize];
		int totalPointsTeamOne = 0;
		int totalPointsTeamTwo = 0;
		for (int i = 0; i < _teamOneSize; i++)
		{
			points = _teamOne[i].getStats().getInteger(POINTS) / getDivider();
			if (points <= 0)
				points = 1;
			else if (points > Config.ALT_OLY_MAX_POINTS)
				points = Config.ALT_OLY_MAX_POINTS;

			totalPointsTeamOne += points;
			pointsTeamOne[i] = points;
			maxPointsTeamOne[i] = points;
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			points = _teamTwo[i].getStats().getInteger(POINTS) / getDivider();
			if (points <= 0)
				points = 1;
			else if (points > Config.ALT_OLY_MAX_POINTS)
				points = Config.ALT_OLY_MAX_POINTS;

			totalPointsTeamTwo += points;
			pointsTeamTwo[i] = points;
			maxPointsTeamTwo[i] = points;
		}

		// Choose minimum sum
		int min = Math.min(totalPointsTeamOne, totalPointsTeamTwo);

		// make sure all team members got same number of the points: round down to 3x
		min = (min / MAX_TEAM_SIZE) * MAX_TEAM_SIZE;

		// calculating coefficients and trying to correct total number of points for each team
		// due to rounding errors total points after correction will always be lower or equal
		// than needed minimal sum
		final double dividerOne = (double)totalPointsTeamOne / min;
		final double dividerTwo = (double)totalPointsTeamTwo / min;
		totalPointsTeamOne = min;
		totalPointsTeamTwo = min;
		for (int i = 0; i < _teamOneSize; i++)
		{
			points = Math.max((int)(pointsTeamOne[i] / dividerOne), 1);
			pointsTeamOne[i] = points;
			totalPointsTeamOne -= points;
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			points = Math.max((int)(pointsTeamTwo[i] / dividerTwo), 1);
			pointsTeamTwo[i] = points;
			totalPointsTeamTwo -= points;
		}

		// compensating remaining points, first team from begin to end, second from end to begin
		for (int i = 0; totalPointsTeamOne > 0 && i < _teamOneSize; i++)
		{
			if (pointsTeamOne[i] < maxPointsTeamOne[i])
			{
				pointsTeamOne[i]++;
				totalPointsTeamOne--;
			}
		}

		for (int i = _teamTwoSize; totalPointsTeamTwo > 0 && --i >= 0;)
		{
			if (pointsTeamTwo[i] < maxPointsTeamTwo[i])
			{
				pointsTeamTwo[i]++;
				totalPointsTeamTwo--;
			}
		}

		// Create results for players if a team crashed
		if (tOneCrash || tTwoCrash)
		{
			try
			{
				if (tTwoCrash && !tOneCrash)
				{
					sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_GAME);
					sm.addString(_teamOne[0].getName());
					stadium.broadcastPacket(sm);

					for (int i = 0; i < _teamTwoSize; i++)
					{
						par = _teamTwo[i];
						par.updateStat(COMP_LOST, 1);
						points = pointsTeamTwo[i];
						removePointsFromParticipant(par, points);
					}

					points = min / MAX_TEAM_SIZE;
					for (int i = 0; i < _teamOneSize; i++)
					{
						par = _teamOne[i];
						par.updateStat(COMP_WON, 1);
						addPointsToParticipant(par, points);
					}

					for (int i = 0; i < _teamOneSize; i++)
						rewardParticipant(_teamOne[i].getPlayer(), getReward());
				}
				else if (tOneCrash && !tTwoCrash)
				{
					sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_GAME);
					sm.addString(_teamTwo[0].getName());
					stadium.broadcastPacket(sm);

					for (int i = 0; i < _teamOneSize; i++)
					{
						par = _teamOne[i];
						par.updateStat(COMP_LOST, 1);
						points = pointsTeamOne[i];
						removePointsFromParticipant(par, points);
					}
					
					points = min / MAX_TEAM_SIZE;
					for (int i = 0; i < _teamTwoSize; i++)
					{
						par = _teamTwo[i];
						par.updateStat(COMP_WON, 1);
						addPointsToParticipant(par, points);
					}

					for (int i = 0; i < _teamTwoSize; i++)
						rewardParticipant(_teamTwo[i].getPlayer(), getReward());
				}
				else if (tOneCrash && tTwoCrash)
				{
					stadium.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_ENDED_IN_A_TIE));

					for (int i = _teamOneSize; --i >= 0;)
					{
						par = _teamOne[i];
						par.updateStat(COMP_LOST, 1);
						removePointsFromParticipant(par, pointsTeamOne[i]);
					}

					for (int i = _teamTwoSize; --i >= 0;)
					{
						par = _teamTwo[i];
						par.updateStat(COMP_LOST, 1);
						removePointsFromParticipant(par, pointsTeamTwo[i]);
					}
				}

				for (int i = _teamOneSize; --i >= 0;)
				{
					par = _teamOne[i];
					par.updateStat(COMP_DONE, 1);
					par.updateStat(COMP_DONE_WEEK, 1);
					par.updateStat(getWeeklyMatchType(), 1);
				}

				for (int i = _teamTwoSize; --i >= 0;)
				{
					par = _teamTwo[i];
					par.updateStat(COMP_DONE, 1);
					par.updateStat(COMP_DONE_WEEK, 1);
					par.updateStat(getWeeklyMatchType(), 1);
				}
			}
			catch (Exception e)
			{
				_log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
			}
			return;
		}
		
		try
		{
			double hp;
			double teamOneHp = 0;
			double teamTwoHp = 0;

			for (int i = _teamOneSize; --i >= 0;)
			{
				par = _teamOne[i];
				if (!par.isDisconnected()
						&& par.getPlayer() != null
						&& !par.getPlayer().isDead())
				{
					hp = par.getPlayer().getCurrentHp() + par.getPlayer().getCurrentCp();
					if (hp >= 0.5)
						teamOneHp += hp;
				}
				par.updatePlayer();
			}

			for (int i = _teamTwoSize; --i >= 0;)
			{
				par = _teamTwo[i];
				if (!par.isDisconnected()
						&& par.getPlayer() != null
						&& !par.getPlayer().isDead())
				{
					hp = par.getPlayer().getCurrentHp() + par.getPlayer().getCurrentCp();
					if (hp >= 0.5)
						teamTwoHp += hp;
				}
				par.updatePlayer();
			}
			
			if ((teamTwoHp == 0 && teamOneHp != 0)
					|| (_damageT1 > _damageT2 && teamTwoHp != 0 && teamOneHp != 0))
			{
				sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_GAME);
				sm.addString(_teamOne[0].getName());
				stadium.broadcastPacket(sm);

				for (int i = 0; i < _teamTwoSize; i++)
				{
					par = _teamTwo[i];
					par.updateStat(COMP_LOST, 1);
					points = pointsTeamTwo[i];
					removePointsFromParticipant(par, points);
				}

				points = min / MAX_TEAM_SIZE;
				for (int i = 0; i < _teamOneSize; i++)
				{
					par = _teamOne[i];
					par.updateStat(COMP_WON, 1);
					addPointsToParticipant(par, points);
				}

				for (int i = 0; i < _teamOneSize; i++)
					rewardParticipant(_teamOne[i].getPlayer(), getReward());
			}
			else if ((teamOneHp == 0 && teamTwoHp != 0)
					|| (_damageT2 > _damageT1 && teamOneHp != 0 && teamTwoHp != 0))
			{
				sm = SystemMessage.getSystemMessage(SystemMessageId.C1_HAS_WON_THE_GAME);
				sm.addString(_teamTwo[0].getName());
				stadium.broadcastPacket(sm);

				for (int i = 0; i < _teamOneSize; i++)
				{
					par = _teamOne[i];
					par.updateStat(COMP_LOST, 1);
					points = pointsTeamOne[i];
					removePointsFromParticipant(par, points);
				}
				
				points = min / MAX_TEAM_SIZE;
				for (int i = 0; i < _teamTwoSize; i++)
				{
					par = _teamTwo[i];
					par.updateStat(COMP_WON, 1);
					addPointsToParticipant(par, points);
				}

				for (int i = 0; i < _teamTwoSize; i++)
					rewardParticipant(_teamTwo[i].getPlayer(), getReward());
			}
			else
			{
				stadium.broadcastPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_GAME_ENDED_IN_A_TIE));

				for (int i = 0; i < _teamOneSize; i++)
				{
					par = _teamOne[i];
					par.updateStat(COMP_DRAWN, 1);
					points = Math.min(par.getStats().getInteger(POINTS) / getDivider(), Config.ALT_OLY_MAX_POINTS);
					removePointsFromParticipant(par, points);
				}

				for (int i = 0; i < _teamTwoSize; i++)
				{
					par = _teamTwo[i];
					par.updateStat(COMP_DRAWN, 1);
					points = Math.min(par.getStats().getInteger(POINTS) / getDivider(), Config.ALT_OLY_MAX_POINTS);
					removePointsFromParticipant(par, points);
				}
			}
			
			for (int i = _teamOneSize; --i >= 0;)
			{
				par = _teamOne[i];
				par.updateStat(COMP_DONE, 1);
				par.updateStat(COMP_DONE_WEEK, 1);
				par.updateStat(getWeeklyMatchType(), 1);
			}

			for (int i = _teamTwoSize; --i >= 0;)
			{
				par = _teamTwo[i];
				par.updateStat(COMP_DONE, 1);
				par.updateStat(COMP_DONE_WEEK, 1);
				par.updateStat(getWeeklyMatchType(), 1);
			}
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
		}
	}
	
	@Override
	protected final void addDamage(L2PcInstance player, int damage)
	{
		Participant par;
		for (int i = _teamOneSize; --i >= 0;)
		{
			par = _teamOne[i];
			if (par.getObjectId() == player.getObjectId())
			{
				if (!par.isDisconnected())
					_damageT1 += damage;
				return;
			}
		}

		for (int i = _teamTwoSize; --i >= 0;)
		{
			par = _teamTwo[i];
			if (par.getObjectId() == player.getObjectId())
			{
				if (!par.isDisconnected())
					_damageT2 += damage;
				return;
			}
		}
	}
	
	@Override
	public final String[] getPlayerNames()
	{
		return new String[] {_teamOne[0].getName(), _teamTwo[0].getName()};
	}

	@Override
	public final boolean checkDefaulted()
	{
		try
		{
			SystemMessage reason = null;
			Participant par;
			for (int i = _teamOneSize; --i >= 0;)
			{
				par = _teamOne[i];
				par.updatePlayer();
				reason = checkDefaulted(par.getPlayer());
				if (reason != null)
				{
					par.setDefaulted(true);
					if (!_teamOneDefaulted)
					{
						_teamOneDefaulted = true;
						for (Participant t : _teamTwo)
						{
							if (t.getPlayer() != null)
								t.getPlayer().sendPacket(reason);
						}
					}
				}
			}

			reason = null;
			for (int i = _teamTwoSize; --i >= 0;)
			{
				par = _teamTwo[i];
				par.updatePlayer();
				reason = checkDefaulted(par.getPlayer());
				if (reason != null)
				{
					par.setDefaulted(true);
					if (!_teamTwoDefaulted)
					{
						_teamTwoDefaulted = true;
						for (Participant t : _teamOne)
						{
							if (t.getPlayer() != null)
								t.getPlayer().sendPacket(reason);
						}
					}
				}
			}
			
			return _teamOneDefaulted || _teamTwoDefaulted;
		}
		catch (Exception e)
		{
			_log.log(Level.WARNING, "Exception on checkDefaulted(): " + e.getMessage(), e);
			return true;
		}
	}

	@Override
	public final void resetDamage()
	{
		_damageT1 = 0;
		_damageT2 = 0;
	}

	protected final boolean teamOneAllDisconnected()
	{
		for (int i = _teamOneSize; --i >= 0;)
		{
			if (!_teamOne[i].isDisconnected())
				return false;
		}

		return true;
	}

	protected final boolean teamTwoAllDisconnected()
	{
		for (int i = _teamTwoSize; --i >= 0;)
		{
			if (!_teamTwo[i].isDisconnected())
				return false;
		}

		return true;
	}
}
