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

import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.handler.IActionHandler;
import com.l2jserver.gameserver.model.Elementals;
import com.l2jserver.gameserver.model.L2DropCategory;
import com.l2jserver.gameserver.model.L2DropData;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Object.InstanceType;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.items.L2Item;
import com.l2jserver.gameserver.model.stats.BaseStats;
import com.l2jserver.gameserver.model.stats.Stats;
import com.l2jserver.gameserver.network.serverpackets.MyTargetSelected;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.StatusUpdate;
import com.l2jserver.util.StringUtil;

public class L2NpcActionShift implements IActionHandler
{
	private static final boolean SHOW_COMBAT_STATS = false;
	/**
	 * Manage and Display the GM console to modify the L2NpcInstance (GM only).<BR><BR>
	 *
	 * <B><U> Actions (If the L2PcInstance is a GM only)</U> :</B><BR><BR>
	 * <li>Set the L2NpcInstance as target of the L2PcInstance player (if necessary)</li>
	 * <li>Send a Server->Client packet MyTargetSelected to the L2PcInstance player (display the select window)</li>
	 * <li>If L2NpcInstance is autoAttackable, send a Server->Client packet StatusUpdate to the L2PcInstance in order to update L2NpcInstance HP bar </li>
	 * <li>Send a Server->Client NpcHtmlMessage() containing the GM console about this L2NpcInstance </li><BR><BR>
	 *
	 * <FONT COLOR=#FF0000><B> <U>Caution</U> : Each group of Server->Client packet must be terminated by a ActionFailed packet in order to avoid
	 * that client wait an other packet</B></FONT><BR><BR>
	 *
	 * <B><U> Example of use </U> :</B><BR><BR>
	 * <li> Client packet : Action</li><BR><BR>
	 */
	@Override
	public boolean action(L2PcInstance activeChar, L2Object targetObject, boolean interact)
	{
		L2Npc target = (L2Npc)targetObject;

		// Check if the L2PcInstance is a GM
		if (activeChar.getAccessLevel().isGm())
		{
			// Set the target of the L2PcInstance activeChar
			activeChar.setTarget(target);
			
			// Send a Server->Client packet MyTargetSelected to the L2PcInstance activeChar
			// The activeChar.getLevel() - getLevel() permit to display the correct color in the select window
			MyTargetSelected my = new MyTargetSelected(target.getObjectId(), activeChar.getLevel() - target.getLevel());
			activeChar.sendPacket(my);
			
			// Check if the activeChar is attackable (without a forced attack)
			if (target.isAutoAttackable(activeChar))
			{
				// Send a Server->Client packet StatusUpdate of the L2NpcInstance to the L2PcInstance to update its HP bar
				StatusUpdate su = new StatusUpdate(target);
				su.addAttribute(StatusUpdate.CUR_HP, (int)target.getCurrentHp());
				su.addAttribute(StatusUpdate.MAX_HP, target.getMaxHp());
				activeChar.sendPacket(su);
			}
			
			NpcHtmlMessage html = new NpcHtmlMessage(0);
			html.setFile(activeChar.getHtmlPrefix(), "data/html/admin/npcinfo.htm");
			
			html.replace("%objid%", target.getObjectId());
			html.replace("%class%", target.getClass().getSimpleName());
			html.replace("%id%",    target.getTemplate().getNpcId());
			html.replace("%lvl%",   target.getTemplate().getLevel());
			html.replace("%name%",  target.getTemplate().getName());
			html.replace("%tmplid%",target.getTemplate().getNpcId());
			html.replace("%aggro%", target.getAggroRange());
			html.replace("%hp%",    (int)target.getCurrentHp());
			html.replace("%hpmax%", target.getMaxHp());
			html.replace("%mp%",    (int)target.getCurrentMp());
			html.replace("%mpmax%", target.getMaxMp());
			double php = target.getCurrentHp() / target.getMaxHp();	//[JOJO]
			double pmp = target.getCurrentMp() / target.getMaxMp();	//[JOJO]
			html.replace("%php%", new java.text.DecimalFormat(php < 0.10 ? "0.0% " : "##0%").format(php));	//[JOJO]
			html.replace("%pmp%", new java.text.DecimalFormat(pmp < 0.10 ? "0.0% " : "##0%").format(pmp));	//[JOJO]
			
			html.replace("%patk%", target.getPAtk(null));
			html.replace("%matk%", target.getMAtk(null, null));
			html.replace("%pdef%", target.getPDef(null));
			html.replace("%mdef%", target.getMDef(null, null));
			html.replace("%accu%", target.getAccuracy());
			html.replace("%evas%", target.getEvasionRate(null));
			html.replace("%crit%", target.getCriticalHit(null, null));
			html.replace("%rspd%", target.getRunSpeed());
			html.replace("%aspd%", target.getPAtkSpd());
			html.replace("%cspd%", target.getMAtkSpd());
			html.replace("%str%",  target.getSTR());
			html.replace("%dex%",  target.getDEX());
			html.replace("%con%",  target.getCON());
			html.replace("%int%",  target.getINT());
			html.replace("%wit%",  target.getWIT());
			html.replace("%men%",  target.getMEN());
			html.replace("%loc%",  target.getX()+" "+target.getY()+" "+target.getZ());
			html.replace("%heading%",  target.getHeading());
			html.replace("%collision_radius%", target.getTemplate().getfCollisionRadius());
			html.replace("%collision_height%", target.getTemplate().getfCollisionHeight());
			//html.replace("%dist%", (int)Math.sqrt(activeChar.getDistanceSq(target)));	//-[JOJO]
			
			byte attackAttribute = target.getAttackElement();
			html.replace("%ele_atk%", Elementals.getElementName(attackAttribute));
			html.replace("%ele_atk_value%", target.getAttackElementValue(attackAttribute));
			html.replace("%ele_dfire%", target.getDefenseElementValue(Elementals.FIRE));
			html.replace("%ele_dwater%", target.getDefenseElementValue(Elementals.WATER));
			html.replace("%ele_dwind%", target.getDefenseElementValue(Elementals.WIND));
			html.replace("%ele_dearth%", target.getDefenseElementValue(Elementals.EARTH));
			html.replace("%ele_dholy%", target.getDefenseElementValue(Elementals.HOLY));
			html.replace("%ele_ddark%", target.getDefenseElementValue(Elementals.DARK));
			
			if (target.getSpawn() != null)
			{
				html.replace("%spawn%", target.getSpawn().getLocx()+" "+target.getSpawn().getLocy()+" "+target.getSpawn().getLocz()+" "+target.getSpawn().getHeading());
				html.replace("%loc2d%", (int)Math.sqrt(target.getPlanDistanceSq(target.getSpawn().getLocx(), target.getSpawn().getLocy())));
				html.replace("%loc3d%", (int)Math.sqrt(target.getDistanceSq(target.getSpawn().getLocx(), target.getSpawn().getLocy(), target.getSpawn().getLocz())));
				html.replace("%locV%" , target.getZ() - target.getSpawn().getLocz());	//[JOJO]
				html.replace("%resp%",  target.getSpawn().getRespawnDelay() / 1000);
			}
			else
			{
				html.replace("%spawn%", "<font color=FF0000>null</font>");
				html.replace("%loc2d%", "<font color=FF0000>--</font>");
				html.replace("%loc3d%", "<font color=FF0000>--</font>");
				html.replace("%locV%" , "<font color=FF0000>--</font>");	//[JOJO]
				html.replace("%resp%",  "<font color=FF0000>--</font>");
			}
			html.replace("%dist2d%", (int)Math.sqrt(target.getPlanDistanceSq(activeChar)));	//[JOJO]
			html.replace("%dist3d%", (int)Math.sqrt(target.getDistanceSq(activeChar)));	//[JOJO]
			html.replace("%distV%" , target.getZ() - activeChar.getZ());	//[JOJO]

if (com.l2jserver.Config.ADMIN_VIEW_NPC_STATUS) {{
			StringBuilder sb = new StringBuilder(256);
			sb.append("<TR><TD><table width=270 border=0><tr><td>");
			L2Object o = target.getTarget();
			if (o != null) sb.append("Target: ").append(o.getName()).append(", Range: ").append((int)com.l2jserver.gameserver.util.Util.calculateDistance(target, o, false)).append("<BR1>");
			if (target.getInstanceId() != 0) sb.append("Instance ID:" + target.getInstanceId()).append("<BR1>");
			if (target.getScriptValue() != 0) sb.append(" v=").append(target.getScriptValue());
			if (target.isAfraid()) sb.append(" Afraid");
			if (target.isAlikeDead()) sb.append(" AlikeDead");
			if (target.isAllSkillsDisabled()) sb.append(" AllSkillsDisabled");
			if (target.isAttackAborted()) sb.append(" AttackAborted");
			if (target.isAttackingDisabled()) sb.append(" AttackingDisabled");
			if (target.isAttackingNow()) sb.append(" AttackingNow");
			if (target.isBetrayed()) sb.append(" Betrayed");
			if (target.isBusy()) sb.append(" Busy");
			if (target.getBusyMessage() != null && target.getBusyMessage().length() > 0) sb.append(" \"").append(target.getBusyMessage()).append("\"");
			if (target.isCastingNow()) sb.append(" CastingNow");
 //			if (target.isCastingNow()) sb.append(" CastingNow(").append(target.getCastEndTimeLeftMilli()).append("ms)");
			if (target.isCastingSimultaneouslyNow()) sb.append(" CastingSimultaneouslyNow");
			if (target.isChampion()) sb.append(" Champion");
			if (target.isConfused()) sb.append(" Confused");
			if (target.isCoreAIDisabled()) sb.append(" CoreAIDisabled");
			if (target.isDead()) sb.append(" Dead");
			if (target.isDebug()) sb.append(" Debug");
			if (target.isDisarmed()) sb.append(" Disarmed");
			if (target.isFallsdown()) sb.append(" Fallsdown");
			if (target.isImmobilized()) sb.append(" Immobilized");
			if (target.isInActiveRegion()) sb.append(" InActiveRegion");
			if (target.isInCombat()) sb.append(" InCombat");
			if (target.isInvul()) sb.append(" Invul");
			if (target.isMinion()) sb.append(" Minion");
			if (target.isMortal()) sb.append(" Mortal");
			if (target.isMovementDisabled()) sb.append(" MovementDisabled");
			if (target.isMoving()) sb.append(" Moving");
			if (target.isMuted()) sb.append(" Muted");
			if (target.isNoRndWalk()) sb.append(" NoRndWalk");
			if (target.isOnGeodataPath()) sb.append(" OnGeodataPath");
			if (target.isOutOfControl()) sb.append(" OutOfControl");
			if (target.isOverloaded()) sb.append(" Overloaded");
			if (target.isParalyzed()) sb.append(" Paralyzed");
			if (target.isPendingRevive()) sb.append(" PendingRevive");
			if (target.isPhysicalAttackMuted()) sb.append(" PhysicalAttackMuted");
			if (target.isPhysicalMuted()) sb.append(" PhysicalMuted");
			if (target.isRaid()) sb.append(" Raid");
			if (target.isRaidMinion()) sb.append(" RaidMinion");
			if (target.isResurrectionBlocked()) sb.append(" ResurrectionBlocked");
			if (target.isRooted()) sb.append(" Rooted");
			if (target.isRunning()) sb.append(" Running");
			if (target.isShowSummonAnimation()) sb.append(" ShowSummonAnimation");
			if (target.isSleeping()) sb.append(" Sleeping");
			if (target.isStunned()) sb.append(" Stunned");
			if (target.isTeleporting()) sb.append(" Teleporting");
			if (target.isTransformed()) sb.append(" Transformed");
			if (target.isUndead()) sb.append(" Undead");
			if (target.isUsingDualWeapon()) sb.append(" UsingDualWeapon");
			if (target instanceof L2Attackable) {
				L2Attackable a = (L2Attackable) target;
				if (a.canReturnToSpawnPoint()) sb.append(" canReturnToSpawnPoint");
				if (a.isReturningToSpawnPoint()) sb.append(" ReturningToSpawnPoint");
				if (a.isSweepActive()) sb.append(" SweepActive");
			}
			sb.append("</td></tr></table></TD></TR>");
			html.replace("%STATUS%", sb.toString());
}} else {{
			html.replace("%STATUS%", "");
}}
			
			html.replace("%ai_intention%",  "<tr><td><table width=270 border=0 bgcolor=131210><tr><td width=100><font color=FFAA00>Intention:</font></td><td align=right width=170>"+(target.hasAI() ? target.getAI().getIntention().name() : "null")+"</td></tr></table></td></tr>");
			html.replace("%ai%",            "<tr><td><table width=270 border=0><tr><td width=100><font color=FFAA00>AI</font></td><td align=right width=170>"+(target.hasAI() ? target.getAI().getClass().getSimpleName() : "null")+"</td></tr></table></td></tr>");
			html.replace("%ai_type%",       "<tr><td><table width=270 border=0 bgcolor=131210><tr><td width=100><font color=FFAA00>AIType</font></td><td align=right width=170>"+target.getAiType().name()+"</td></tr></table></td></tr>");
			html.replace("%ai_clan%",       "<tr><td><table width=270 border=0><tr><td width=100><font color=FFAA00>Clan & Range:</font></td><td align=right width=170>"+target.getTemplate().getAIDataStatic().getClan()+" "+target.getTemplate().getAIDataStatic().getClanRange()+"</td></tr></table></td></tr>");
			html.replace("%ai_enemy_clan%", "<tr><td><table width=270 border=0 bgcolor=131210><tr><td width=100><font color=FFAA00>Enemy & Range:</font></td><td align=right width=170>"+target.getTemplate().getAIDataStatic().getEnemyClan()+" "+target.getTemplate().getAIDataStatic().getEnemyRange()+"</td></tr></table></td></tr>");
			
			if (target instanceof L2MerchantInstance)
			{
				html.replace("%butt%","<button value=\"Shop\" action=\"bypass -h admin_showShop "+target.getTemplate().getNpcId()+"\" width=60 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">");
			}
			else
			{
				html.replace("%butt%","");
			}
			
			activeChar.sendPacket(html);
		}
		else if (Config.ALT_GAME_VIEWNPC)
		{
			// Set the target of the L2PcInstance activeChar
			activeChar.setTarget(target);
			
			// Send a Server->Client packet MyTargetSelected to the L2PcInstance activeChar
			// The activeChar.getLevel() - getLevel() permit to display the correct color in the select window
			MyTargetSelected my = new MyTargetSelected(target.getObjectId(), activeChar.getLevel() - target.getLevel());
			activeChar.sendPacket(my);
			
			// Check if the activeChar is attackable (without a forced attack)
			if (target.isAutoAttackable(activeChar))
			{
				// Send a Server->Client packet StatusUpdate of the L2NpcInstance to the L2PcInstance to update its HP bar
				StatusUpdate su = new StatusUpdate(target);
				su.addAttribute(StatusUpdate.CUR_HP, (int) target.getCurrentHp());
				su.addAttribute(StatusUpdate.MAX_HP, target.getMaxHp());
				activeChar.sendPacket(su);
			}
			
			NpcHtmlMessage html = new NpcHtmlMessage(0);
			final StringBuilder html1 = StringUtil.startAppend(
					1000,
					"<html><body>");
			if (SHOW_COMBAT_STATS) {
				int hpMul = Math.round((float)(target.getStat().calcStat(Stats.MAX_HP, 1, target, null) / BaseStats.CON.calcBonus(target)));
				if (hpMul == 0)
					hpMul = 1;
				StringUtil.append(html1, "<br><center><font color=\"LEVEL\">[Combat Stats]</font></center>" +
					"<table border=0 width=\"100%\">" +
					"<tr><td>Max.HP</td><td>",
					String.valueOf(target.getMaxHp() / hpMul),
					"*",
					String.valueOf(hpMul),
					"</td><td>Max.MP</td><td>",
					String.valueOf(target.getMaxMp()),
					"</td></tr>" +
					"<tr><td>P.Atk.</td><td>",
					String.valueOf(target.getPAtk(null)),
					"</td><td>M.Atk.</td><td>",
					String.valueOf(target.getMAtk(null, null)),
					"</td></tr>" +
					"<tr><td>P.Def.</td><td>",
					String.valueOf(target.getPDef(null)),
					"</td><td>M.Def.</td><td>",
					String.valueOf(target.getMDef(null, null)),
					"</td></tr>" +
					"<tr><td>Accuracy</td><td>",
					String.valueOf(target.getAccuracy()),
					"</td><td>Evasion</td><td>",
					String.valueOf(target.getEvasionRate(null)),
					"</td></tr>" +
					"<tr><td>Critical</td><td>",
					String.valueOf(target.getCriticalHit(null, null)),
					"</td><td>Speed</td><td>",
					String.valueOf(target.getRunSpeed()),
					"</td></tr>" +
					"<tr><td>Atk.Speed</td><td>",
					String.valueOf(target.getPAtkSpd()),
					"</td><td>Cast.Speed</td><td>",
					String.valueOf(target.getMAtkSpd()),
					"</td></tr>" +
					"<tr><td>Race</td><td>",
					target.getTemplate().getRace().toString(),
					"</td><td></td><td></td></tr>" +
					"</table>" +
					"<br><center><font color=\"LEVEL\">[Basic Stats]</font></center>" +
					"<table border=0 width=\"100%\">" +
					"<tr><td>STR</td><td>",
					String.valueOf(target.getSTR()),
					"</td><td>DEX</td><td>",
					String.valueOf(target.getDEX()),
					"</td><td>CON</td><td>",
					String.valueOf(target.getCON()),
					"</td></tr>" +
					"<tr><td>INT</td><td>",
					String.valueOf(target.getINT()),
					"</td><td>WIT</td><td>",
					String.valueOf(target.getWIT()),
					"</td><td>MEN</td><td>",
					String.valueOf(target.getMEN()),
					"</td></tr>" +
					"</table>"
				);
			}
			
			if (target.getTemplate().getDropData().size() > 0)
			{
				// Edited AltGameViewNpc
				// http://www.l2jserver.com/forum/viewtopic.php?f=73&t=18450
				StringUtil.append(html1,
						"<br><center><font color=LEVEL>[Drop Info]</font></center>" +
						"<br>Rates legend: <font color=ff0000>50%+</font> <font color=ffff00>30%+</font> <font color=00ff00>less than 30%</font>" +
						"<table border=0 width=100%>"
				);
				for (L2DropCategory cat : target.getTemplate().getDropData())
				{
					for (L2DropData drop : cat.getAllDrops())
					{
						final L2Item item = ItemTable.getInstance().getTemplate(drop.getItemId());
						if (item == null)
							continue;
						
						final String color;
						final String category;
						final double chance;
						
						if (drop.isQuestDrop())
						{
							category = "<font color=ff8000>Quest</font>";
							chance = drop.getChance();
						}
						else if (cat.isSweep())
						{
							category = "<font color=ff00ff>Sweep</font>";
							chance = drop.getChance() * Config.RATE_DROP_SPOIL;
						}
						else
						{
							category = "Drop";
							chance = drop.getChance() * Config.RATE_DROP_ITEMS;
						}
						if (drop.isQuestDrop())
							color = "ff8000";
						else if (chance >= 500000)
							color = "ff0000";
						else if (chance >= 300000)
							color = "ffff00";
						else
							color = "00ff00";
						
						StringUtil.append(html1,
								  "<tr>"
								+ "<td><img src=\"", item.getIcon(), "\" height=32 width=32></td>"
								+ "<td><font color=", color, ">&#", String.valueOf(item.getItemId()), ";</font></td>"
								+ "<td width=50>", category, "</td>"
								+ "</tr>"
						);
					}
				}
				html1.append("</table>");
			}
			else
			{
				html1.append("Droplist is not available.");
			}
			html1.append("</body></html>");
			
			html.setHtml(html1.toString());
			activeChar.sendPacket(html);
		}
		return true;
	}
	
	@Override
	public InstanceType getInstanceType()
	{
		return InstanceType.L2Npc;
	}
}
