/*
 * Copyright (C) 2004-2013 L2J DataPack
 * 
 * This file is part of L2J DataPack.
 * 
 * L2J DataPack 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.
 * 
 * L2J DataPack 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 ai.individual.Sailren;

import static com.l2jserver.gameserver.datatables.SkillTable.*;
import ai.npc.AbstractNpcAI;

import com.l2jserver.gameserver.instancemanager.GlobalVariablesManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.TeleportWhereType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jserver.gameserver.model.zone.type.L2NoRestartZone;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.SpecialCamera;

/**
 * Sailren AI.
 * @author St3eT
 */
public final class Sailren extends AbstractNpcAI
{
	// NPCs
	private static final int STATUE = 32109; // Shilen's Stone Statue
	private static final int MOVIE_NPC = 32110; // Invisible NPC for movie
	private static final int SAILREN = 29065; // Sailren
	private static final int VELOCIRAPTOR = 22218; // Velociraptor
	private static final int PTEROSAUR = 22199; // Pterosaur
	private static final int TREX = 22217; // Tyrannosaurus
	private static final int CUBIC = 32107; // Teleportation Cubic
	// Item
	private static final int GAZKH = 8784; // Gazkh
	// Skill
	private static final int ANIMATION = getSkillHashCode(5090, 1);	// サイレン演出
	// Zone
	private static final L2NoRestartZone zone = ZoneManager.getInstance().getZoneById(70049, L2NoRestartZone.class);
	// Misc
	private static /*final*/ boolean CAN_SINGLE_PLAYER = false; // Whether to enable the entry of a single player. (EnableSinglePlayer)
	
	private static final long TIME_SPAWN_PTEROSAUR = 20_000;	// (IntervalOfNextMonster)
	private static final long TIME_SPAWN_TREX = 20_000;		// (IntervalOfNextMonster)
	private static final long TIME_SPAWN_SAILREN = 180_000;	// (IntervalOfNextMonster)
	private static final long TIME_OUT_QUBIC = 300_000;
	private static final long TIME_RESPAWN_SAILREN = 3600_000; // Sailren respawn time (FixIntervalOfSailrenSpawn)
	private static final long TIME_OUT_GAME = 3200_000; // Max time for game (ActivityTimeOfMobs)
	private static final long TIME_OUT_ATTACK = 600_000;
	
	private static Status _status = Status.ALIVE;
	private static int _killCount = 0;
	private static long _lastAttack = 0;
	
	private static enum Status
	{
		ALIVE,
		IN_FIGHT,
		DEAD
	}
	
	private Sailren()
	{
		super(Sailren.class.getSimpleName(), "ai/individual");
		addStartNpc(STATUE, CUBIC);
		addTalkId(STATUE, CUBIC);
		addFirstTalkId(STATUE);
		addKillId(VELOCIRAPTOR, PTEROSAUR, TREX, SAILREN);
		addAttackId(VELOCIRAPTOR, PTEROSAUR, TREX, SAILREN);
		
		final long remain = GlobalVariablesManager.getInstance().getLong("SailrenRespawn", 0) - System.currentTimeMillis();
		if (remain > 0)
		{
			_status = Status.DEAD;
			startQuestTimer("CLEAR_STATUS", remain, null, null);
		}
	}
	
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		switch (event)
		{
			case "32109-01.html":
			case "32109-01a.html":
			case "32109-02a.html":
			case "32109-03a.html":
			{
				return event;
			}
			case "enter":
			{
				String htmltext = null;
				if (!CAN_SINGLE_PLAYER && !player.isInParty())
				{
					htmltext = "32109-01.html";
				}
				else if (_status == Status.DEAD)
				{
					htmltext = "32109-04.html";
				}
				else if (_status == Status.IN_FIGHT)
				{
					htmltext = "32109-05.html";
				}
				else if (!CAN_SINGLE_PLAYER && !player.getParty().isLeader(player))
				{
					htmltext = "32109-03.html";
				}
				else if (!hasQuestItems(player, GAZKH))
				{
					htmltext = "32109-02.html";
				}
				else
				{
					takeItems(player, 1, GAZKH);
					_status = Status.IN_FIGHT;
					_killCount = 0;
					_lastAttack = System.currentTimeMillis();
					if (CAN_SINGLE_PLAYER && !player.isInParty())
					{
						player.teleToLocation(27549, -6638, -2008);
					}
					else
					{
						for (L2PcInstance member : player.getParty().getMembers())
						{
							if (member.isInsideRadius(npc, 1000, true, false))
							{
								member.teleToLocation(27549, -6638, -2008);
							}
						}
					}
					startQuestTimer("SPAWN_VELOCIRAPTOR", 60000, null, null);
					startQuestTimer("TIME_OUT", TIME_OUT_GAME, null, null);
					startQuestTimer("CHECK_ATTACK", 120000, null, null);
				}
				return htmltext;
			}
			case "teleportOut":
			{
				player.teleToLocation(TeleportWhereType.TOWN);
				break;
			}
			case "SPAWN_VELOCIRAPTOR":
			{
				for (int i = 0; i < 3; i++)
				{
					addSpawn(VELOCIRAPTOR, 27313 + getRandom(150), -6766 + getRandom(150), -1975, 0, false, 0);
				}
				break;
			}
			case "SPAWN_PTEROSAUR":
			{
				final L2Attackable pterosaur = (L2Attackable) addSpawn(PTEROSAUR, 27313, -6766, -1975, 0, false, 0);
				attackPlayer(pterosaur, player);
				break;
			}
			case "SPAWN_TREX":
			{
				final L2Attackable trex = (L2Attackable) addSpawn(TREX, 27313, -6766, -1975, 0, false, 0);
				attackPlayer(trex, player);
				break;
			}
			case "SPAWN_SAILREN":
			{
				final L2RaidBossInstance sailren = (L2RaidBossInstance) addSpawn(SAILREN, 27549, -6638, -2008, 0, false, 0);
				final L2Npc movieNpc = addSpawn(MOVIE_NPC, sailren.getX(), sailren.getY(), sailren.getZ() + 30, 0, false, 0);
				sailren.setIsInvul(true);
				sailren.setIsImmobilized(true);
				zone.broadcastPacket(new SpecialCamera(movieNpc, 60, 110, 30, 4000, 1500, 20000, 0, 65, 1, 0, 0));
				
				startQuestTimer("ATTACK", 24600, sailren, null);
				startQuestTimer("ANIMATION", 2000, movieNpc, null);
				startQuestTimer("CAMERA_1", 4100, movieNpc, null);
				break;
			}
			case "ANIMATION":
			{
				if (npc.isVisible())
				{
					npc.setTarget(npc);
					npc.doCast(getSkill(ANIMATION));
					startQuestTimer("ANIMATION", 2000, npc, null);
				}
				break;
			}
			case "CAMERA_1":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 100, 180, 30, 3000, 1500, 20000, 0, 50, 1, 0, 0));
				startQuestTimer("CAMERA_2", 3000, npc, null);
				break;
			}
			case "CAMERA_2":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 150, 270, 25, 3000, 1500, 20000, 0, 30, 1, 0, 0));
				startQuestTimer("CAMERA_3", 3000, npc, null);
				break;
			}
			case "CAMERA_3":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 160, 360, 20, 3000, 1500, 20000, 10, 15, 1, 0, 0));
				startQuestTimer("CAMERA_4", 3000, npc, null);
				break;
			}
			case "CAMERA_4":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 160, 450, 10, 3000, 1500, 20000, 0, 10, 1, 0, 0));
				startQuestTimer("CAMERA_5", 3000, npc, null);
				break;
			}
			case "CAMERA_5":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 160, 560, 5, 3000, 1500, 20000, 0, 15, 1, 0, 0));
				startQuestTimer("CAMERA_6", 7000, npc, null);
				break;
			}
			case "CAMERA_6":
			{
				zone.broadcastPacket(new SpecialCamera(npc, 70, 560, 0, 500, 1500, 7000, -15, 20, 1, 0, 0));
				startQuestTimer("CAMERA_9", 2000, npc, null);
				break;
			}
			case "CAMERA_9":
			{
				npc.deleteMe();
				break;
			}
			case "ATTACK":
			{
				npc.setIsInvul(false);
				npc.setIsImmobilized(false);
				_lastAttack = System.currentTimeMillis();
				break;
			}
			case "CLEAR_STATUS":
			{
				_status = Status.ALIVE;
				break;
			}
			case "TIME_OUT":
			{
				if (_status == Status.IN_FIGHT)
				{
					_status = Status.ALIVE;
				}
				for (L2Character charInside : zone.getCharactersInside())
				{
					if (charInside != null)
					{
						if (charInside.isPlayer())
						{
							charInside.teleToLocation(TeleportWhereType.TOWN);
						}
						else if (charInside.isNpc())
						{
							charInside.deleteMe();
						}
					}
				}
				break;
			}
			case "CHECK_ATTACK":
			{
				if (!zone.getPlayersInside().isEmpty() && ((_lastAttack + TIME_OUT_ATTACK) < System.currentTimeMillis()))
				{
					cancelQuestTimer("TIME_OUT", null, null);
					notifyEvent("TIME_OUT", null, null);
				}
				else
				{
					startQuestTimer("CHECK_ATTACK", 120000, null, null);
				}
				break;
			}
		}
		return super.onAdvEvent(event, npc, player);
	}
	
	@Override
	public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon)
	{
		if (zone.isCharacterInZone(attacker))
		{
			_lastAttack = System.currentTimeMillis();
		}
		return super.onAttack(npc, attacker, damage, isSummon);
	}
	
	@Override
	public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
	{
		if (zone.isCharacterInZone(killer))
		{
			switch (npc.getId())
			{
				case SAILREN:
				{
					_status = Status.DEAD;
					cancelQuestTimer("TIME_OUT", null, null);
					cancelQuestTimer("CHECK_ATTACK", null, null);
					addSpawn(CUBIC, 27644, -6638, -2008, 0, false, 300000);
					final long respawnTime = TIME_RESPAWN_SAILREN;
					GlobalVariablesManager.getInstance().set("SailrenRespawn", System.currentTimeMillis() + respawnTime);
					startQuestTimer("CLEAR_STATUS", respawnTime, null, null);
					startQuestTimer("TIME_OUT", TIME_OUT_QUBIC, null, null);
					break;
				}
				case VELOCIRAPTOR:
				{
					final boolean b;
					synchronized (this) { b = ++_killCount == 3; }
					if (b)
						startQuestTimer("SPAWN_PTEROSAUR", TIME_SPAWN_PTEROSAUR, null, killer);
					break;
				}
				case PTEROSAUR:
				{
					startQuestTimer("SPAWN_TREX", TIME_SPAWN_TREX, null, killer);
					break;
				}
				case TREX:
				{
					startQuestTimer("SPAWN_SAILREN", TIME_SPAWN_SAILREN, null, null);
					npc.broadcastPacket(new NpcSay(npc.getObjectId(), 1, npc.getId(), 1800011/*わ〜い！ご主人様のお戻りだ。必ず仕返ししてくださるはず！お前ももうちょっとで死体だよ。*/));
					break;
				}
			}
		}
		return super.onKill(npc, killer, isSummon);
	}
	
	@Override
	public boolean unload(boolean removeFromList)
	{
		if (_status == Status.IN_FIGHT)
		{
			_log.info(getClass().getSimpleName() + ": Script is being unloaded while Sailren is active, clearing zone.");
			notifyEvent("TIME_OUT", null, null);
		}
		return super.unload(removeFromList);
	}
	
	public static void main(String[] args)
	{
		new Sailren();
	}
}
