package lasteam.gameserver.instancemanager.clanhallsiege;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.apache.log4j.Logger;


import lasteam.gameserver.ThreadPoolManager;
import lasteam.gameserver.datatables.ClanTable;
import lasteam.gameserver.datatables.NpcTable;
import lasteam.gameserver.datatables.xml.DoorTable;
import lasteam.gameserver.idfactory.IdFactory;
import lasteam.gameserver.instancemanager.ClanHallManager;
import lasteam.gameserver.instancemanager.ClanHallSiege;
import lasteam.gameserver.instancemanager.MapRegionManager;
import lasteam.gameserver.instancemanager.ZoneManager;
import lasteam.gameserver.model.L2Character;
import lasteam.gameserver.model.L2Clan;
import lasteam.gameserver.model.L2ItemInstance;
import lasteam.gameserver.model.L2World;
import lasteam.gameserver.model.actor.instance.L2MonsterInstance;
import lasteam.gameserver.model.actor.instance.L2PcInstance;
import lasteam.gameserver.model.actor.instance.L2SiegeFlagInstance;
import lasteam.gameserver.model.entity.ClanHall;
import lasteam.gameserver.model.mapregion.L2MapRegion;
import lasteam.gameserver.model.zone.L2ClanhallZone;
import lasteam.gameserver.model.zone.L2Zone;
import lasteam.gameserver.network.SystemChatChannelId;
import lasteam.gameserver.network.serverpackets.CreatureSay;
import lasteam.gameserver.templates.chars.L2NpcTemplate;
import lasteam.gameserver.threadmanager.ExclusiveTask;

/*
*
* Author: MHard - L2CatsSoftware DevTeam
*
*/
public class WildBeastFarmSiege extends ClanHallSiege
{
	protected static Logger 				_log	= Logger.getLogger(WildBeastFarmSiege.class.getName());
	private static WildBeastFarmSiege			_instance;
	private boolean								_registrationPeriod = false;
	private int									_clanCounter = 0;
	private Map<Integer, clanPlayersInfo>		_clansInfo		= new  FastMap<Integer, clanPlayersInfo>().setShared(true);
	private L2Zone zone = ZoneManager.getInstance().getZone(L2Zone.ZoneType.Clanhall, "Beast Farm");
	public ClanHall clanhall = ClanHallManager.getInstance().getClanHallById(63);
	private clanPlayersInfo						_ownerClanInfo=new clanPlayersInfo();
	private boolean								_finalStage = false;
	private ScheduledFuture<?>					_midTimer;

	public static final WildBeastFarmSiege load()
	{
		_log.info("SiegeManager of Wild Beasts Farm");
		if (_instance == null)
			_instance = new WildBeastFarmSiege();
		return _instance;
	}

	public static final WildBeastFarmSiege getInstance()
	{
		if (_instance == null)
			_instance = new WildBeastFarmSiege();
		return _instance;
	}
	private WildBeastFarmSiege()
	{
		long siegeDate=restoreSiegeDate(63);
		Calendar tmpDate=Calendar.getInstance();
		tmpDate.setTimeInMillis(siegeDate);
		setSiegeDate(tmpDate);		
		setNewSiegeDate(siegeDate,63,22);
		// Schedule siege auto start
		_startSiegeTask.schedule(1000);
	}
	public void startSiege()
	{
		setRegistrationPeriod(false);
		if(_clansInfo.size()==0)
		{
			endSiege(false);
			return;
		}
		if((_clansInfo.size()==1)&&(clanhall.getOwnerClan()==null))
		{
			endSiege(false);
			return;
		}
		if((_clansInfo.size()==1)&&(clanhall.getOwnerClan()!=null))
		{
			L2Clan clan=null;
			for (clanPlayersInfo a : _clansInfo.values())
				clan=ClanTable.getInstance().getClanByName(a._clanName);
			setIsInProgress(true);
			((L2ClanhallZone)zone).updateSiegeStatus();
			startSecondStep(clan);
			anonce("Займите места у своих осадных штабов.",1);
			_siegeEndDate = Calendar.getInstance();
			_siegeEndDate.add(Calendar.MINUTE, 30);
			_endSiegeTask.schedule(1000);
			return;
		}
		setIsInProgress(true);
		clanhall.setUnderSiege(true);
		((L2ClanhallZone)zone).updateSiegeStatus();
		spawnFlags();
		gateControl(1);
		anonce("Займите места у своих осадных штабов.",1);
		ThreadPoolManager.getInstance().scheduleGeneral(new startFirstStep(), 5*60000);
		_midTimer=ThreadPoolManager.getInstance().scheduleGeneral(new midSiegeStep(), 25*60000);
		_siegeEndDate = Calendar.getInstance();
		_siegeEndDate.add(Calendar.MINUTE, 60);
		_endSiegeTask.schedule(1000);
	}
	public void startSecondStep(L2Clan winner)
	{
		FastList<String> winPlayers = WildBeastFarmSiege.getInstance().getRegisteredPlayers(winner);
		unSpawnAll();
		_clansInfo.clear();
		clanPlayersInfo regPlayers = new clanPlayersInfo();
		regPlayers._clanName=winner.getName();
		regPlayers._players=winPlayers;
		_clansInfo.put(winner.getClanId(), regPlayers);
		_clansInfo.put(clanhall.getOwnerClan().getClanId(),_ownerClanInfo);
		spawnFlags();
		gateControl(1);
		_finalStage = true;
		anonce("Займите места у своих осадных штабов.",1);
		ThreadPoolManager.getInstance().scheduleGeneral(new startFirstStep(), 5*60000);
	}
	public void endSiege(boolean par)
	{
		_mobControlTask.cancel();
		_finalStage = false;
		if (par)
		{
			L2Clan winner=checkHaveWinner();
			if(winner!=null)
			{
				ClanHallManager.getInstance().setOwner(clanhall.getId(),winner);
				anonce("Внимание !!! Холл Клана, Ферма Диких Зверей был завоеван кланом "+winner.getName(),2);
			}
			else
				anonce("Внимание !!! Холл Клана, Ферма Диких Зверей не получил нового владельца",2);
		}
		setIsInProgress(false);
		clanhall.setUnderSiege(false);
		((L2ClanhallZone)zone).updateSiegeStatus();
		unSpawnAll();
		_clansInfo.clear();
		_clanCounter = 0;
		teleportPlayers();
		setNewSiegeDate(getSiegeDate().getTimeInMillis(),63,22);
		_startSiegeTask.schedule(1000);
	}
	public void unSpawnAll()
	{
		for(String clanName:getRegisteredClans())
		{
			L2Clan clan=ClanTable.getInstance().getClanByName(clanName);
			L2MonsterInstance mob=getQuestMob(clan);
			L2SiegeFlagInstance flag=getSiegeFlag(clan);
			if (mob!=null)
				mob.deleteMe();
			if (flag!=null)
				flag.deleteMe();
		}
	}
	public void gateControl(int val)
	{
		if (val==1)
		{
			DoorTable.getInstance().getDoor(21150003).openMe();
			DoorTable.getInstance().getDoor(21150004).openMe();
			DoorTable.getInstance().getDoor(21150001).closeMe();
			DoorTable.getInstance().getDoor(21150002).closeMe();
		}
		else if (val==2)
		{
			DoorTable.getInstance().getDoor(21150001).closeMe();
			DoorTable.getInstance().getDoor(21150002).closeMe();
			DoorTable.getInstance().getDoor(21150003).closeMe();
			DoorTable.getInstance().getDoor(21150004).closeMe();
		}
	}
	public void teleportPlayers()
	{
		for(L2Character cha : zone.getCharactersInside().values())
			if (cha instanceof L2PcInstance)
			{
				L2Clan clan=((L2PcInstance)cha).getClan();
				if (!isPlayerRegister(clan,cha.getName()))
					cha.teleToLocation(53468, -94092, -1634);
			}
	}
	public L2Clan checkHaveWinner()
	{
		L2Clan res=null;
		int questMobCount=0;
		for(String clanName:getRegisteredClans())
		{
			L2Clan clan=ClanTable.getInstance().getClanByName(clanName);
			if (getQuestMob(clan)!=null)
			{
				res=clan;
				questMobCount++;
			}
		}
		if (questMobCount>1)
			return null;
		return res;
	}
	private class midSiegeStep implements Runnable 
	{
		public void run()
		{
			_mobControlTask.cancel();
			L2Clan winner=checkHaveWinner();
			if(winner!=null)
			{
				if (clanhall.getOwnerClan()==null)
				{
					ClanHallManager.getInstance().setOwner(clanhall.getId(),winner);
					anonce("Внимание !!! Холл Клана, Фкрма Диких Зверей был завоеван кланом "+winner.getName(),2);
					endSiege(false);
				}
				else
					startSecondStep(winner);
			}
			else
			{
				endSiege(true);
			}
		}
	}
	private class startFirstStep implements Runnable 
	{
		public void run()
		{
			teleportPlayers();
			gateControl(2);
			int mobCounter=1;
			for(String clanName:getRegisteredClans())
			{
				L2NpcTemplate template;
				L2Clan clan=ClanTable.getInstance().getClanByName(clanName);
				template = NpcTable.getInstance().getTemplate(35617+mobCounter);
				template.setServerSideTitle(true);
				template.setTitle(clan.getName());
				L2MonsterInstance questMob = new L2MonsterInstance(IdFactory.getInstance().getNextId(), template);
				questMob.setHeading(100);
				questMob.getStatus().setCurrentHpMp(questMob.getMaxHp(), questMob.getMaxMp());
				if (mobCounter==1)
					questMob.spawnMe(57069,-91797,-1360);
				else if (mobCounter==2)
					questMob.spawnMe(58838,-92232,-1354);
				else if (mobCounter==3)
					questMob.spawnMe(57327,-93373,-1365);
				else if (mobCounter==4)
					questMob.spawnMe(57820,-91740,-1354);
				else if (mobCounter==5)
					questMob.spawnMe(58728,-93487,-1360);
				clanPlayersInfo regPlayers = _clansInfo.get(clan.getClanId());
				regPlayers._mob=questMob;
				mobCounter++;
			}
			_mobControlTask.schedule(3000);
			anonce("Бой начался. Убейте НПЦ противника",1);
		}
	}
	public void spawnFlags()
	{
		int flagCounter=1;
		for(String clanName:getRegisteredClans())
		{
			L2NpcTemplate template;
			L2Clan clan=ClanTable.getInstance().getClanByName(clanName);
			if (clan==clanhall.getOwnerClan())
				template = NpcTable.getInstance().getTemplate(35422);
			else
				template = NpcTable.getInstance().getTemplate(35422+flagCounter);
			L2SiegeFlagInstance flag = new L2SiegeFlagInstance(null, IdFactory.getInstance().getNextId(), template, false,true,clan);
			flag.setTitle(clan.getName());
			flag.setHeading(100);
			flag.getStatus().setCurrentHpMp(flag.getMaxHp(), flag.getMaxMp());
			if (clan==clanhall.getOwnerClan())
				flag.spawnMe(58782,-93180,-1354);
			else
			{
			if (flagCounter==1)
				flag.spawnMe(56769,-92097,-1360);
			else if (flagCounter==2)
				flag.spawnMe(59138,-92532,-1354);
			else if (flagCounter==3)
				flag.spawnMe(57027,-93673,-1365);
			else if (flagCounter==4)
				flag.spawnMe(58120,-91440,-1354);
			else if (flagCounter==5)
				flag.spawnMe(58428,-93787,-1360);
			}
			clanPlayersInfo regPlayers = _clansInfo.get(clan.getClanId());
			regPlayers._flag=flag;
			flagCounter++;
		}
	}
	public void setRegistrationPeriod(boolean par)
	{
		_registrationPeriod = par;
	}
	public boolean isRegistrationPeriod()
	{
		return _registrationPeriod;
	}
	public boolean isPlayerRegister(L2Clan playerClan,String playerName)
	{
		if (playerClan==null)
			return false;
		clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
		if (regPlayers != null)
			if (regPlayers._players.contains(playerName))
				return true;
		return false;
	}
	public boolean isClanOnSiege(L2Clan playerClan)
	{
		if (playerClan==clanhall.getOwnerClan())
			return true;		
		clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
		if (regPlayers == null)
		{
			return false;
		}
		return true;
	}
	public synchronized int registerClanOnSiege(L2PcInstance player,L2Clan playerClan)
	{
		if (_clanCounter==5)
			return 2;
		L2ItemInstance item=player.getInventory().getItemByItemId(8293);		
		if ((item!=null)&&(player.destroyItemWithoutTrace("Consume", item.getObjectId(), 1, null, false)))
		{
			_clanCounter++;
			clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
			if (regPlayers == null)
			{
				regPlayers = new clanPlayersInfo();
				regPlayers._clanName=playerClan.getName();
				_clansInfo.put(playerClan.getClanId(), regPlayers);
			}
		}
		else
			return 1;
		return 0;
	}
	public boolean unRegisterClan(L2Clan playerClan)
	{
		if(_clansInfo.remove(playerClan.getClanId())!=null)
		{
			_clanCounter--;
			return true;
		}
		return false;		
	}
	public FastList<String> getRegisteredClans()
	{
		FastList<String> clans=new FastList<String>();
		for (clanPlayersInfo a : _clansInfo.values())
		{
			clans.add(a._clanName);
		}
		return clans;
	}
	public FastList<String> getRegisteredPlayers(L2Clan playerClan)
	{
		if (playerClan==clanhall.getOwnerClan())
			return _ownerClanInfo._players;
		clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
		if (regPlayers != null)
			return regPlayers._players;
		return null;
	}
	public L2SiegeFlagInstance getSiegeFlag(L2Clan playerClan)
	{
		clanPlayersInfo clanInfo=_clansInfo.get(playerClan.getClanId());
		if(clanInfo!=null)
			return clanInfo._flag;
		return null;
	}
	public L2MonsterInstance getQuestMob(L2Clan clan)
	{
		clanPlayersInfo clanInfo=_clansInfo.get(clan.getClanId());
		if(clanInfo!=null)
			return clanInfo._mob;
		return null;
	}
	public int getPlayersCount(String playerClan)
	{
		for (clanPlayersInfo a : _clansInfo.values())
			if(a._clanName==playerClan)
				return a._players.size();
		return 0;
	}
	public void addPlayer(L2Clan playerClan,String playerName)
	{
		if (playerClan==clanhall.getOwnerClan())
			if (_ownerClanInfo._players.size()<18)
				if (!_ownerClanInfo._players.contains(playerName))
				{
					_ownerClanInfo._players.add(playerName);
					return;
				}
		clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
		if (regPlayers != null)
			if (regPlayers._players.size()<18)
				if (!regPlayers._players.contains(playerName))
					regPlayers._players.add(playerName);
	}
	public void removePlayer(L2Clan playerClan,String playerName)
	{
		if (playerClan==clanhall.getOwnerClan())
			if (_ownerClanInfo._players.contains(playerName))
			{
				_ownerClanInfo._players.remove(playerName);
				return;
			}
		clanPlayersInfo regPlayers = _clansInfo.get(playerClan.getClanId());
		if (regPlayers != null)
			if (regPlayers._players.contains(playerName))
				regPlayers._players.remove(playerName);
	}
	private final ExclusiveTask _startSiegeTask = new ExclusiveTask(){
		@Override
		protected void onElapsed()
		{
			if (getIsInProgress())
			{
				cancel();
				return;
			}
			Calendar siegeStart=Calendar.getInstance();
			siegeStart.setTimeInMillis(getSiegeDate().getTimeInMillis());
			final long registerTimeRemaining = siegeStart.getTimeInMillis() - System.currentTimeMillis();
			siegeStart.add(Calendar.HOUR, 1);
			final long siegeTimeRemaining = siegeStart.getTimeInMillis() - System.currentTimeMillis();
			long remaining=registerTimeRemaining;
			if (registerTimeRemaining <= 0)
			{
				if (!isRegistrationPeriod())
				{
					if (clanhall.getOwnerClan()!=null)
						_ownerClanInfo._clanName=clanhall.getOwnerClan().getName();
					else
						_ownerClanInfo._clanName="";
					setRegistrationPeriod(true);
					anonce("Внимание !!! Начался период регистрации на осаду Холл Клана , Ферма Диких Зверей.",2);
					remaining=siegeTimeRemaining;
				}
			}
			if (siegeTimeRemaining <= 0)
			{
				startSiege();
				cancel();
				return;
			}
			schedule(remaining);
		}
	};
	public void anonce(String text,int type)
	{
		if (type==1)
		{
			CreatureSay cs = new CreatureSay(0, SystemChatChannelId.Chat_Shout, "Вестник", text);
			for(String clanName:getRegisteredClans())
			{
				L2Clan clan=ClanTable.getInstance().getClanByName(clanName);
				for(String playerName:getRegisteredPlayers(clan))
				{
					L2PcInstance cha = L2World.getInstance().getPlayer(playerName);
					if (cha!=null)
						cha.sendPacket(cs);
				}
			}
		}
		else
		{
			CreatureSay cs = new CreatureSay(0, SystemChatChannelId.Chat_Shout, "Вестник", text);
			L2MapRegion region = MapRegionManager.getInstance().getRegion(53508, -93776, -1584);
			for (L2PcInstance player : L2World.getInstance().getAllPlayers())
			{
				if (region == MapRegionManager.getInstance().getRegion(player.getX(), player.getY(), player.getZ())
						&& (player.getInstanceId() == 0))
				{
					player.sendPacket(cs);
				}
			}
		}
	}
	private final ExclusiveTask _endSiegeTask = new ExclusiveTask() {
		@Override
		protected void onElapsed()
		{
			if (!getIsInProgress())
			{
				cancel();
				return;
			}
			final long timeRemaining = _siegeEndDate.getTimeInMillis() - System.currentTimeMillis();
			if (timeRemaining <= 0)
			{
				endSiege(true);
				cancel();
				return;
			}
			schedule(timeRemaining);
		}
	};
	private final ExclusiveTask _mobControlTask = new ExclusiveTask() {
		@Override
		protected void onElapsed()
		{
			int mobCount=0;
			synchronized(_clansInfo) {
				for(Integer  key :_clansInfo.keySet()) {
					clanPlayersInfo cl = _clansInfo.get(key);
					if (cl._mob.isDead())
					{
						L2Clan clan = ClanTable.getInstance().getClanByName(cl._clanName);					
						unRegisterClan(clan);
					}
					else
						mobCount++;
				}
			}
			teleportPlayers();
			if (mobCount<2)
				if (_finalStage)
				{
					_siegeEndDate = Calendar.getInstance();
					_endSiegeTask.cancel();
					_endSiegeTask.schedule(5000);
				}
				else
				{
					_midTimer.cancel(false);
					ThreadPoolManager.getInstance().scheduleGeneral(new midSiegeStep(), 5000);
				}
			else
				schedule(3000);
		}
	};

	private class clanPlayersInfo
	{
		public String _clanName;
		public L2SiegeFlagInstance _flag = null;
		public L2MonsterInstance _mob = null;
		public FastList<String> _players	= new FastList<String>();
	}
}