/*
 * Copyright (C) 2005-2008 L2J_JP / 2008-2013 L2J-SFJP
 * 
 * This file is part of L2J Server.
 * 
 * L2J Server 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 Server 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.npc.NpcBuffers.impl;

import static com.l2jserver.gameserver.datatables.SkillTable.*;

import java.util.concurrent.ScheduledFuture;

import ai.npc.AbstractNpcAI;

import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.ZoneManager;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.effects.L2Effect;
import com.l2jserver.gameserver.model.skills.AbnormalType;
import com.l2jserver.gameserver.model.skills.L2Skill;
import com.l2jserver.gameserver.model.skills.L2SkillType;
import com.l2jserver.gameserver.model.zone.type.L2TownZone;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;

//@formatter:off
/**
 * @author JOJO
 * 
 * NPC          127     こたつ (type: L2Npc)
 * |アイテム    20868   こたつ - 村から一定距離以上離れたところで召喚すると、HP・MPの回復効果が発揮されます。トレード、ドロップはできません。
 * |召喚スキル  22127-1 温かなこたつ召喚
 * |BUFスキル   22118-1 こたつのぬくもり - こたつのぬくもりが感じられます。HP回復力が40%、CP回復力が30%、MP回復力が20%増加している状態。
 */
public class KotatsuBuffer extends AbstractNpcAI
{
	private static final int KOTATSU = 127;
	
	static final int WARMTH_OF_KOTATZ = getSkillHashCode(22118, 1);
	
	static final int MIN_NPC_ANIMATION = 40000;
	static final int MAX_NPC_ANIMATION = 120000;
	
	private KotatsuBuffer()
	{
		super(KotatsuBuffer.class.getSimpleName(), "ai/npc/NpcBuffers/impl");
		addFirstTalkId(KOTATSU);
		addSpawnId(KOTATSU);
		if (getSkill(WARMTH_OF_KOTATZ).getSkillType() == L2SkillType.NOTDONE) throw new RuntimeException();
	}
	
	@Override
	public String onFirstTalk(L2Npc npc, L2PcInstance player)
	{
		return null;
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
		npc.setShowSummonAnimation(false);
		
		final L2Skill skill = ZoneManager.getInstance().getZone(npc, L2TownZone.class) == null ? getSkill(WARMTH_OF_KOTATZ) : null;
		new KotatsuAI(npc, skill);
		return null;
	}
	
	private static class KotatsuAI implements Runnable
	{
		private final L2Npc _npc;
		private final L2Skill _skill;
		private final ScheduledFuture<?> _aiTask;
		
		/** Time of last social packet broadcast*/
		private long _lastSocialBroadcast = 0;
		/** Minimum interval between social packets*/
		private int _minimalSocialInterval = MIN_NPC_ANIMATION;
		
		protected KotatsuAI(L2Npc npc, L2Skill skill)
		{
			_npc = npc;
			_skill = skill;
			_aiTask = ThreadPoolManager.getInstance().scheduleGeneralWithFixedDelay(this, 3000, 3000);
		}
		
		@Override
		public void run()
		{
			if (!_npc.isVisible())
			{
				_aiTask.cancel(false);
				return;
			}
			
			if (_npc.getKnownList().getKnownPlayers().size() == 0)
				return;
			
			if (_skill != null)
			{
				final int skillRadius = _skill.getAffectRange();
				for (L2PcInstance player : _npc.getKnownList().getKnownPlayers().values())
				{
					if (player == null || !player.isVisible() || player.isInvul() || player.isMovementDisabled())
						continue;
					if (player.getPkKills() > 5)
						continue;
					if (!player.isInsideRadius(_npc, skillRadius, true, true))
						continue;
					if (player.getCurrentHp() < player.getMaxHp()
					 || player.getCurrentCp() < player.getMaxCp()
					 || player.getCurrentMp() < player.getMaxMp())
					{
						handleEffect(player, _skill);
					}
				}
			}
			randomAnimation(Rnd.get(1, 3));
		}
		
		private void handleEffect(L2PcInstance player, L2Skill skill)
		{
			if (! doesStack(player, skill))
			{
				skill.getEffects(player, player);
				player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_FEEL_S1_EFFECT)
					.addSkillName(skill));
			}
		}
		
		private boolean doesStack(L2PcInstance player, L2Skill checkSkill)
		{
			AbnormalType type = checkSkill.getAbnormalType();
			for (L2Effect e : player.getAllEffects())
				if (e.getSkill().getAbnormalType() == type)
					return true;
			return false;
		}
		
		/**
		 * Send a packet SocialAction to all L2PcInstance in the _KnownPlayers of the L2NpcInstance.<BR><BR>
		 */
		private void randomAnimation(int animationId)
		{
			// Send a packet SocialAction to all L2PcInstance in the _KnownPlayers of the L2NpcInstance
			long now = System.currentTimeMillis();
			if (now - _lastSocialBroadcast > _minimalSocialInterval)
			{
				_lastSocialBroadcast = now;
				_minimalSocialInterval = Rnd.get(MIN_NPC_ANIMATION, MAX_NPC_ANIMATION);
				_npc.broadcastPacket(new SocialAction(_npc, animationId));
			}
		}
	}
	
	public static void main(String[] args)
	{
		new KotatsuBuffer();
	}
}
