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

import static com.l2jserver.gameserver.util.GameTimeFunction.currentTime;
import ai.npc.AbstractNpcAI;

import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Spawn;
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.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.holders.SkillHolder;
import com.l2jserver.gameserver.model.skills.L2Skill;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.util.Util;

/**
 * Monastery AI.
 * @author Kerberos, nonom
 */
public class Monastery extends AbstractNpcAI
{
	private static final int CAPTAIN = 18910;
	private static final int KNIGHT = 18909;
	private static final int SCARECROW = 18912;
	
	private static final int AGGRO_RANGE_SCARECROW = 300;	//[JOJO]
	private static final int AGGRO_RANGE_PLAYER = 500;	//[JOJO]
	
	private static final int MINIMAL_SHOUT_INTERVAL = 90;	//[JOJO]
	
	private static final int[] SOLINA_CLAN =
	{
		22789, // Guide Solina
		22790, // Seeker Solina
		22791, // Savior Solina
		22793, // Ascetic Solina
	};
	
	private static final int[] DIVINITY_CLAN =
	{
		22794, // Divinity Judge
		22795, // Divinity Manager
	};
	
	private static final NpcStringId[] SOLINA_KNIGHTS_MSG =
	{
		NpcStringId.PUNISH_ALL_THOSE_WHO_TREAD_FOOTSTEPS_IN_THIS_PLACE,
		NpcStringId.WE_ARE_THE_SWORD_OF_TRUTH_THE_SWORD_OF_SOLINA,
		NpcStringId.WE_RAISE_OUR_BLADES_FOR_THE_GLORY_OF_SOLINA
	};
	
	private static final NpcStringId[] DIVINITY_MSG =
	{
		NpcStringId.S1_WHY_WOULD_YOU_CHOOSE_THE_PATH_OF_DARKNESS,
		NpcStringId.S1_HOW_DARE_YOU_DEFY_THE_WILL_OF_EINHASAD
	};
	
	private static final SkillHolder DECREASE_SPEED = new SkillHolder(4589, 8);
	
	private Monastery()
	{
		super(Monastery.class.getSimpleName(), "ai/group_template");
		addSeeCreatureId(SOLINA_CLAN);
		addSeeCreatureId(CAPTAIN, KNIGHT);
		addSkillSeeId(DIVINITY_CLAN);
		addAttackId(KNIGHT, CAPTAIN);
		addSpawnId(KNIGHT);
		addSpawnId(SCARECROW);
		
if (!com.l2jserver.Config.FIX_onSpawn_for_SpawnTable) {{
		for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(SCARECROW))
		{
			onSpawn(spawn.getLastSpawn());
		}
}}
	}
	
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		EVENT:
		if (event == "checking")
		{
			final L2Attackable me = (L2Attackable) npc;
			
			if (me.isDead() || !me.isVisible() || me.getKnownList().getKnownPlayers().isEmpty())
			{
				cancelQuestTimer(event, npc, player);
				break EVENT;
			}
			
			if (me.isInCombat() && me.getTarget() instanceof L2Playable)
			{
				break EVENT;
			}
			for (L2PcInstance pc : me.getKnownList().getKnownPlayers().values())
			{
				if (autoAttackCondition(me, pc) && Util.checkIfInRange(AGGRO_RANGE_PLAYER, me, pc, true) && GeoData.getInstance().canSeeTarget(me, pc))
				{
					switch (me.getId())
					{
						case CAPTAIN:
						case KNIGHT:
						{
							me.setRunning();
							me.setTarget(pc);
							me.addDamageHate(pc, 0, 999);
							me.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, pc, null);
							break EVENT;
						}
						default:
						{
							if (pc.getActiveWeaponInstance() != null)
							{
								me.setRunning();
								me.setTarget(pc);
								if (getRandom(10) < 2)
								{
									broadcastNpcSay(me, Say2.NPC_ALL, NpcStringId.YOU_CANNOT_CARRY_A_WEAPON_WITHOUT_AUTHORIZATION);
								}
								me.doCast(DECREASE_SPEED.getSkill());
								me.addDamageHate(pc, 0, 999);
								me.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, pc, null);
								break EVENT;
							}
						}
					}
				}
			}
			
			if (me.getId() == KNIGHT)
			{
				if (me.isInCombat()/* && me.getTarget() instanceof L2Npc*/)
				{
					break EVENT;
				}
				for (L2Object obj : me.getKnownList().getKnownObjects().values())
				{
					L2Npc scarecrow;
					if (obj.isNpc() && (scarecrow =((L2Npc) obj)).getId() == SCARECROW && Util.checkIfInRange(AGGRO_RANGE_SCARECROW, me, scarecrow, true))
					{
						for (L2Skill skill : me.getAllSkills())
						{
							if (skill.isActive())
							{
								me.disableSkill(skill, 0);
							}
						}
						me.setRunning();
						me.setTarget(scarecrow);
						me.addDamageHate(scarecrow, 0, 100);
						me.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, scarecrow, null);
						break EVENT;
					}
				}
			}
		}
		return super.onAdvEvent(event, npc, player);
	}
	
	private boolean autoAttackCondition(L2Attackable me, L2PcInstance target)
	{
		if (target.isInvul() && target.isGM()) return false;
		if (target.isAlikeDead()) return false;
		if (target.getAppearance().getInvisible()) return false;
		if (!me.canSeeThroughSilentMove() && target.isSilentMoving()) return false;
		return true;
	}
	
	@Override
	public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
	{
		final int now = currentTime();
		if (npc.getScriptValue() < now)
		{
			npc.setScriptValue(now + MINIMAL_SHOUT_INTERVAL);
			broadcastNpcSay(npc, Say2.NPC_ALL, SOLINA_KNIGHTS_MSG[getRandom(SOLINA_KNIGHTS_MSG.length)]);
		}
		return super.onAttack(npc, player, damage, isSummon);
	}
	
	@Override
	public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
	{
		if (creature.isPlayer())
		{
			startQuestTimer("checking", 5000, npc, null, true);
		}
		return super.onSeeCreature(npc, creature, isSummon);
	}
	
	@Override
	public String onSkillSee(L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isSummon)
	{
		if (skill.hasEffectType(L2EffectType.AGGRESSION) && (targets.length != 0))
		{
			for (L2Object obj : targets)
			{
				if (obj.equals(npc))
				{
					npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), DIVINITY_MSG[getRandom(DIVINITY_MSG.length)]).addPcName(caster));
					((L2Attackable) npc).addDamageHate(caster, 0, 999);
					npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, caster);
					break;
				}
			}
		}
		return super.onSkillSee(npc, caster, skill, targets, isSummon);
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
		switch (npc.getId())
		{
			case KNIGHT:
				broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.FOR_THE_GLORY_OF_SOLINA);
				break;
			case SCARECROW:
				npc.setIsInvul(true);
				npc.disableCoreAI(true);
				break;
		}
		return super.onSpawn(npc);
	}
	
	public static void main(String[] args)
	{
		new Monastery();
	}
}
