/*
 * 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 mods.eventmodRabbits;

import static com.l2jserver.gameserver.model.actor.instance.L2EventChestInstance.autoChat;

import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture;

import com.l2jserver.Config;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2EventChestInstance;
import com.l2jserver.gameserver.model.actor.instance.L2EventMonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.Event;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;

public class eventmodRabbits extends Event
{
	// Event NPC's list
	private ArrayList<L2Npc> _npclist;	//[JOJO] need random access.
	// Event Task
	ScheduledFuture<?> _eventTask = null;
	// Event time
	public static final int _event_time = 10;
	// Event state
	private static boolean _isactive = false;
	// Current Chest count
	private static int _chest_count = 0;
	// How much Chests
	private static final int _option_howmuch = 100;
	// NPc's
	public static final int _npc_snow  = 900101;
	public static final int _npc_chest = 900102;
	// Skills
	public static final int _skill_tornado = 630;
	public static final int _skill_magic_eye = 629;
	
	// Drop data
	private static final int[][] DROPLIST =
	{
		{  1540,  20, 10, 15 },	// Quick Healing Potion
		{  1538,  20,  5, 10 },	// Blessed Scroll of Escape
		{  3936,  20,  5, 10 },	// Blessed Scroll of Ressurection
		{  6387,  15,  5, 10 },	// Blessed Scroll of Ressurection Pets
		{ 22025,  10,  5, 10 },	// Powerful Healing Potion
		{  6622,   5,  1, 1 },	// Giant's Codex
		{ 20034,   5,  1, 1 },	// Revita Pop
		{ 20004,   4,  1, 1 },	// Energy Ginseng
		{ 20004,   1,  1, 1 }	// Energy Ginseng
	};
	
	//[JOJO]-------------------------------------------------
	private static final int[][] BONUSLIST =
	{
		// data/extractable_skills.csv
		// data/stats/items/10200-10299.xml + <set name="handler" val="ItemSkills" />
		{ 10259, 33, 1, 1 },	// 宝物の袋：6級品 - 強化魔法ジュース
		{ 10258, 24, 1, 1 },	// 宝物の袋：5級品 - カクテル セット
		{ 10257, 18, 1, 1 },	// 宝物の袋：4級品 - Cグレード/Dグレード強化スクロール、幻影アガシオン、祝福された帰還スクロール
		{ 10273, 12, 1, 1 },	// 搭乗用ウルフ召喚ブレスレット（幻影兵器）
		{ 10256,  7, 1, 1 },	// 宝物の袋：3級品 - Aグレード/Bグレード強化スクロール、生命の石、祝福された復活スクロール
		{ 10255,  5, 1, 1 },	// 宝物の袋：2級品 - Sグレード強化スクロール、下巨人の秘伝書（忘却/修練/熟練編）、属性石
		{ 10254,  1, 1, 1 },	// 宝物の袋：1級品 - Sグレード防具、ソウル ストーン：ステップ13〜14
	};
	
	private static final int DROPLIST_TOTAL_CHANCE, BONUSLIST_TOTAL_CHANCE;
	static {
		int chance = 0;
		for (int[]i : DROPLIST)
			chance += i[1];
		DROPLIST_TOTAL_CHANCE = chance;
		chance = 0;
		for (int[]i : BONUSLIST)
			chance += i[1];
		BONUSLIST_TOTAL_CHANCE = chance;
	}
	
	private static final int DUMMY_CHEST = 13097;
	private L2Npc _dummy_chest;
	ScheduledFuture<?> _sayTask = null;
	
	private static final int[] DONDON_SAY =
	{
		1600020,	//Startled	ドンドンッ。
		1600021,	//Bumps	ガタゴトッ。
	};
	
	private static final int[] ON_DROP_SAY =
	{
		1600006,	//You've made a great choice.	よくぞ選んでくれました！
	};
	//-------------------------------------------------------
	
	public static void main(String[] args)
	{
		new eventmodRabbits(-1, "eventmodRabbits", "mods");
	}
	
	public eventmodRabbits(int questId, String name, String descr)
	{
		super(questId, name, descr);
		
		addStartNpc(_npc_snow);
		addFirstTalkId(_npc_snow);
		addTalkId(_npc_snow);
		
		addFirstTalkId(_npc_chest);
		addSkillSeeId(_npc_chest);
		addSpawnId(_npc_chest);
		addAttackId(_npc_chest);
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
		((L2EventMonsterInstance)npc).eventSetDropOnGround(true);
		((L2EventMonsterInstance)npc).eventSetBlockOffensiveSkills(true);
		
		npc.setIsImmobilized(true);
		npc.disableCoreAI(true);
		
		return super.onSpawn(npc);
	}
	
	@Override
	public boolean eventStart()
	{
		// Don't start event if its active
		if(_isactive)
			return false;
		
		// Check Custom Table - we use custom NPC's
		if (!Config.CUSTOM_NPC_TABLE)
			return false;
		
		// Initialize list
		_npclist = new ArrayList<L2Npc>(_option_howmuch + 1);
		
		// Set Event active
		_isactive = true;
		
		// Spawn Manager
		recordSpawn(_npc_snow, -59227, -56939, -2039, 64106, false, 0);
		_dummy_chest = addSpawn(DUMMY_CHEST, -59227, -56939, -2039, 64106, false, 0);	//+[JOJO]
		
		// Spawn Chests
		for(int i=0; i < _option_howmuch; i++)
		{
			int x = Rnd.get(-60653, -58772);
			int y = Rnd.get(-55830, -57718);
			recordSpawn(_npc_chest, x, y, -2030, 0, true, _event_time*60*1000);
			_chest_count++;
		}
		
		// Announce event start
		Announcements.getInstance().announceToAll("ウサギ イベント - 宝箱出現！");
		Announcements.getInstance().announceToAll("幻想の島で待ってま〜す。ステキなお宝をGetしてね〜★");
		Announcements.getInstance().announceToAll("制限時間は"+_event_time+"分だよ．．．");
		
		// Schedule Event end
		_eventTask = ThreadPoolManager.getInstance().scheduleGeneral(new Runnable()
		{
			public void run()
			{
				timeUp();
			}
		}, _event_time*60*1000);
		
		//[JOJO]-------------------------------------------------
		_sayTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new Runnable()
		{
			public void run()
			{
				final int size = _npclist.size();
				for (int i = 0, index = Rnd.get(size); i < size; ++i, index = (index + 1) % size)
				{
					L2Npc obj = _npclist.get(index);
					if (obj instanceof L2EventChestInstance)
					{
						L2EventChestInstance chest = (L2EventChestInstance)obj;
						if (!chest.isTriggered() && !chest.isDead() && !chest.isDecayed())
						{
							_dummy_chest.teleToLocation(chest.getX(), chest.getY(), chest.getZ());
							do { try { Thread.sleep(1000); } catch (InterruptedException e) { } } while (_dummy_chest.isTeleporting());
							autoChat(_dummy_chest, DONDON_SAY, Say2.ALL);
							break;/*for*/
						}
					}
				}
			}
		}, 10000, 3000);
		//-------------------------------------------------------
		
		return true;
	}
	
	private void timeUp()
	{
		Announcements.getInstance().announceToAll("時間切れ！");
		eventStop();
	}
	
	@Override
	public boolean eventStop()
	{
		// Don't stop inactive event
		if(!_isactive)
			return false;
		
		// Set inactive
		_isactive = false;
		
		// Cancel task if any
		if (_eventTask != null)
		{
			_eventTask.cancel(true);
			_eventTask = null;
		}
		//[JOJO]-------------------------------------------------
		if (_sayTask != null)
		{
			_sayTask.cancel(true);
			_sayTask = null;
		}
		//-------------------------------------------------------
		// Despawn Npc's
		if(!_npclist.isEmpty())
		{
			for (L2Npc _npc : _npclist)
				if (_npc != null)
					_npc.deleteMe();
		}
		_npclist.clear();
		_npclist = null;			//+[JOJO]
		_dummy_chest.deleteMe();	//+[JOJO]
		_dummy_chest = null;		//+[JOJO]
		
		// Announce event end
		Announcements.getInstance().announceToAll("ウサギ イベントは終わったよ。");
		
		return true;
	}
	
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		String htmltext = event;
		
		if (event.equalsIgnoreCase("transform"))
		{
			if (player.isTransformed() || player.isInStance())
				player.untransform();
			
			SkillTable.getInstance().getInfo(2428, 1).getEffects(npc, player);
			
			return null;
		}
		return htmltext;
	}
	
	@Override
	public String onFirstTalk(L2Npc npc, L2PcInstance player)
	{
	//-[JOJO]
	//	QuestState st = player.getQuestState(getName());
	//	if (st == null)
	//	{
	//		Quest q = QuestManager.getInstance().getQuest(getName());
	//		st = q.newQuestState(player);
	//	}
		return npc.getNpcId()+".htm";
	}
	
	@Override
	public String onSkillSee(L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isPet)
	{
		if (Util.contains(targets,npc))
		{
			if(skill.getId() == _skill_tornado)
			{
				autoChat(npc, ON_DROP_SAY, Say2.ALL);	//+[JOJO]
				dropItem(npc, caster, DROPLIST, DROPLIST_TOTAL_CHANCE);
				L2EventChestInstance chest = (L2EventChestInstance)npc;
				if (chest.hasBonus())
					dropItem(npc, caster, BONUSLIST, BONUSLIST_TOTAL_CHANCE);
				npc.doDie(npc);	//+[JOJO]
			//	npc.deleteMe();	//-[JOJO]
				
				final int chest_count; synchronized (this) { chest_count = --_chest_count; }	//+[JOJO]
			//	_chest_count--;																	//-[JOJO]
			//	
				if(chest_count <= 0)	//+[JOJO]
			//	if(_chest_count <= 0)	//-[JOJO]
				{
					Announcements.getInstance().announceToAll("宝箱は全部無くなったよ。");
					eventStop();
				}
			}
			else if (skill.getId() == _skill_magic_eye)
			{
			//	if(npc instanceof L2EventChestInstance)
					((L2EventChestInstance)npc).trigger();
			}
		}
		return super.onSkillSee(npc,caster,skill,targets,isPet);
	}
	
	@Override
	public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isPet, L2Skill skill)
	{
		// Some retards go to event and disturb it by breaking chests
		// So... Apply raid curse if player don't use skill on chest but attack it
		if(_isactive && npc.getNpcId() == _npc_chest)
		{
			SkillTable.getInstance().getInfo(4515, 1).getEffects(npc, attacker);
			npc.deleteMe();						//+[JOJO]
			//TODO: --_chest_count;
		}
		
		return super.onAttack(npc, attacker, damage, isPet);
	}
	
	private static final void dropItem(L2Npc mob, L2PcInstance player, int[][] droplist, int total)
	{
		int chance = Rnd.get(total);
		
		for (int i = 0; i < droplist.length; i++)
		{
			int[] drop = droplist[i];
			if ((chance -= drop[1]) < 0)
			{
				((L2MonsterInstance)mob).dropItem(player, drop[0], Rnd.get(drop[2], drop[3]));
				return;
			}
		}
	}
	
	private L2Npc recordSpawn(int npcId, int x, int y, int z, int heading, boolean randomOffSet, long despawnDelay)
	{
		L2Npc _tmp = addSpawn(npcId, x, y, z, heading, randomOffSet, despawnDelay);
		if(_tmp != null)
			_npclist.add(_tmp);
		return _tmp;
	}
	
	@Override
	public boolean eventBypass(L2PcInstance activeChar, String bypass)
	{
		return false;
	}
}
