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

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.TradeController;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.handler.IAdminCommandHandler;
import com.l2jserver.gameserver.model.L2DropCategory;
import com.l2jserver.gameserver.model.L2DropData;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.L2TradeList;
import com.l2jserver.gameserver.model.L2TradeList.L2TradeItem;
import com.l2jserver.gameserver.model.actor.instance.L2MerchantInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.templates.StatsSet;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
import com.l2jserver.gameserver.templates.item.L2Item;
import com.l2jserver.gameserver.util.StringUtil;

/**
 * @author terry
 * 
 */
public class AdminEditNpcT23 implements IAdminCommandHandler
{
	private static Logger _log = Logger.getLogger(AdminEditChar.class.getName());
	private static final boolean L2J_JP = true;
	private final static int PAGE_LIMIT = 7;
	
	private static final String[] ADMIN_COMMANDS =
	{
		"admin_show_skilllist_npc",	// [L2J_JP ADD]
		"admin_edit_skill_npc",		// [L2J_JP ADD]
		"admin_add_skill_npc",		// [L2J_JP ADD]
		"admin_del_skill_npc",		// [L2J_JP ADD]
		"admin_edit_npc",
		"admin_save_npc",
		"admin_show_droplist",
		"admin_edit_drop",
		"admin_add_drop",
		"admin_del_drop",
		"admin_showShop",
		"admin_showShopList",
		"admin_addShopItem",
		"admin_delShopItem",
		"admin_editShopItem",
		"admin_close_window"
	};
	
	public boolean useAdminCommand(String command, L2PcInstance activeChar)
	{
		//TODO: Tokenize and protect arguments parsing. Externalize HTML.
		if (command.startsWith("admin_showShop "))
		{
			String[] args = command.split(" ");
			if (args.length > 1)
				showShop(activeChar, Integer.parseInt(command.split(" ")[1]));
		}
		else if (command.startsWith("admin_showShopList "))
		{
			String[] args = command.split(" ");
			if (args.length > 2)
				showShopList(activeChar, Integer.parseInt(command.split(" ")[1]), Integer.parseInt(command.split(" ")[2]));
		}
		else if (command.startsWith("admin_edit_npc "))
		{
			try
			{
				String[] commandSplit = command.split(" ");
				int npcId = Integer.parseInt(commandSplit[1]);
				L2NpcTemplate npc = NpcTable.getInstance().getTemplate(npcId);
				Show_Npc_Property(activeChar, npc);
			}
			catch (Exception e)
			{
				activeChar.sendMessage("Wrong usage: //edit_npc <npcId>");
			}
		}
		else if (command.startsWith("admin_show_droplist "))
		{
if (L2J_JP) {{
			// [L2J_JP EDIT START]
			StringTokenizer st = new StringTokenizer(command, " ");
			int npcId = -1;
			int page = 0;
			try
			{
				st.nextToken();
				if (st.hasMoreTokens())
					npcId = Integer.parseInt(st.nextToken());
				if (st.hasMoreTokens())
					page = Integer.parseInt(st.nextToken());
			}
			catch (Exception e)
			{
			}
			
			if (npcId > 0)
				showNpcDropList(activeChar, npcId, page);
			else
				activeChar.sendMessage("Wrong usage: //show_droplist <npc_id> <page>");
			// [L2J_JP EDIT END]
}} else {{
			int npcId = 0;
			try
			{
				npcId = Integer.parseInt(command.substring(20).trim());
			}
			catch (Exception e)
			{
			}
			
			if (npcId > 0)
				showNpcDropList(activeChar, npcId);
			else
				activeChar.sendMessage("Usage: //show_droplist <npc_id>");
}}
		}
		else if (command.startsWith("admin_addShopItem "))
		{
			String[] args = command.split(" ");
			if (args.length > 1)
				addShopItem(activeChar, args);
		}
		else if (command.startsWith("admin_delShopItem "))
		{
			String[] args = command.split(" ");
			if (args.length > 2)
				delShopItem(activeChar, args);
		}
		else if (command.startsWith("admin_editShopItem "))
		{
			String[] args = command.split(" ");
			if (args.length > 2)
				editShopItem(activeChar, args);
		}
		else if (command.startsWith("admin_save_npc "))
		{
			try
			{
				save_npc_property(activeChar, command);
			}
			catch (StringIndexOutOfBoundsException e)
			{
			}
		}

		// [L2J_JP ADD START]
		else if (command.startsWith("admin_show_skilllist_npc "))
		{
			StringTokenizer st = new StringTokenizer(command.substring(25), " ");
			try
			{
				int npcId = -1;
				int page = 0;
				if (st.countTokens() <= 2)
				{
					if (st.hasMoreTokens())
						npcId = Integer.parseInt(st.nextToken());
					if (st.hasMoreTokens())
						page = Integer.parseInt(st.nextToken());
				}
				
				if (npcId > 0)
				{
					showNpcSkillList(activeChar, npcId, page);
				}
				else
				{
					activeChar.sendMessage("Wrong usage: //show_skilllist_npc <npc_id> <page> ");
				}
			}
			catch (Exception e)
			{
				// Case of wrong monster data
				activeChar.sendMessage("Wrong usage: //show_skilllist_npc <npc_id> <page>");
			}
		}
        else if (command.startsWith("admin_edit_skill_npc "))
		{
			int npcId = -1, skillId = -1;
			try
			{
				StringTokenizer st = new StringTokenizer(command.substring(21).trim(), " ");
				if (st.countTokens() == 2)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						skillId = Integer.parseInt(st.nextToken());
						showNpcSkillEdit(activeChar, npcId, skillId);
					}
					catch (Exception e)
					{
					}
				}
				else if (st.countTokens() == 3)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						skillId = Integer.parseInt(st.nextToken());
						int level = Integer.parseInt(st.nextToken());
						
						updateNpcSkillData(activeChar, npcId, skillId, level);
					}
					catch (Exception e)
					{
						_log.fine("admin_edit_skill_npc parements error: " + command);
					}
				}
				else
				{
					activeChar.sendMessage("Wrong usage: //edit_skill_npc <npc_id> <item_id> [<level>]");
				}
			}
			catch (StringIndexOutOfBoundsException e)
			{
				activeChar.sendMessage("Wrong usage: //edit_skill_npc <npc_id> <item_id> [<level>]");
			}
		}
        else if (command.startsWith("admin_add_skill_npc "))
		{
			int npcId = -1, skillId = -1;
			try
			{
				StringTokenizer st = new StringTokenizer(command.substring(20).trim(), " ");
				if (st.countTokens() == 1)
				{
					try
					{
						String[] input = command.substring(20).split(" ");
						if (input.length < 1)
							return true;
						npcId = Integer.parseInt(input[0]);
					}
					catch (Exception e)
					{
					}
					
					if (npcId > 0)
					{
						L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
						showNpcSkillAdd(activeChar, npcData);
					}
				}
				else if (st.countTokens() == 3)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						skillId = Integer.parseInt(st.nextToken());
						int level = Integer.parseInt(st.nextToken());
						
						addNpcSkillData(activeChar, npcId, skillId, level);
					}
					catch (Exception e)
					{
						_log.fine("admin_add_skill_npc parements error: " + command);
					}
				}
				else
				{
					activeChar.sendMessage("Wrong usage: //add_skill_npc <npc_id> [<level>]");
				}
			}
			catch (StringIndexOutOfBoundsException e)
			{
				activeChar.sendMessage("Wrong usage: //add_skill_npc <npc_id> [<level>]");
			}
		}
		else if (command.startsWith("admin_del_skill_npc "))
		{
			int npcId = -1, skillId = -1;
			try
			{
				String[] input = command.substring(20).split(" ");
				if (input.length >= 2)
				{
					npcId = Integer.parseInt(input[0]);
					skillId = Integer.parseInt(input[1]);
				}
			}
			catch (Exception e)
			{
			}
			
			if (npcId > 0)
			{
				deleteNpcSkillData(activeChar, npcId, skillId);
			}
			else
			{
				activeChar.sendMessage("Wrong usage: //del_skill_npc <npc_id> <skill_id>");
			}
		}
		// [L2J_JP ADD END]

		else if (command.startsWith("admin_edit_drop "))
		{
			int npcId = -1, itemId = 0, category = -1000;
			try
			{
				StringTokenizer st = new StringTokenizer(command.substring(16).trim());
				if (st.countTokens() == 3)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						itemId = Integer.parseInt(st.nextToken());
						category = Integer.parseInt(st.nextToken());
						showEditDropData(activeChar, npcId, itemId, category);
					}
					catch (Exception e)
					{
					}
				}
				else if (st.countTokens() == 6)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						itemId = Integer.parseInt(st.nextToken());
						category = Integer.parseInt(st.nextToken());
						int min = Integer.parseInt(st.nextToken());
						int max = Integer.parseInt(st.nextToken());
						int chance = Integer.parseInt(st.nextToken());
						
						updateDropData(activeChar, npcId, itemId, min, max, category, chance);
					}
					catch (Exception e)
					{
						_log.fine("admin_edit_drop parements error: " + command);
					}
				}
				else
					activeChar.sendMessage("Usage: //edit_drop <npc_id> <item_id> <category> [<min> <max> <chance>]");
			}
			catch (StringIndexOutOfBoundsException e)
			{
				activeChar.sendMessage("Usage: //edit_drop <npc_id> <item_id> <category> [<min> <max> <chance>]");
			}
		}
		else if (command.startsWith("admin_add_drop "))
		{
			int npcId = -1;
			try
			{
				StringTokenizer st = new StringTokenizer(command.substring(15).trim());
				if (st.countTokens() == 1)
				{
					try
					{
						String[] input = command.substring(15).split(" ");
						if (input.length < 1)
							return true;
						npcId = Integer.parseInt(input[0]);
					}
					catch (Exception e)
					{
					}
					
					if (npcId > 0)
					{
						L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
						showAddDropData(activeChar, npcData);
					}
				}
				else if (st.countTokens() == 6)
				{
					try
					{
						npcId = Integer.parseInt(st.nextToken());
						int itemId = Integer.parseInt(st.nextToken());
						int category = Integer.parseInt(st.nextToken());
						int min = Integer.parseInt(st.nextToken());
						int max = Integer.parseInt(st.nextToken());
						int chance = Integer.parseInt(st.nextToken());
						
						addDropData(activeChar, npcId, itemId, min, max, category, chance);
					}
					catch (Exception e)
					{
						_log.fine("admin_add_drop parements error: " + command);
					}
				}
				else
					activeChar.sendMessage("Usage: //add_drop <npc_id> [<item_id> <category> <min> <max> <chance>]");
			}
			catch (StringIndexOutOfBoundsException e)
			{
				activeChar.sendMessage("Usage: //add_drop <npc_id> [<item_id> <category> <min> <max> <chance>]");
			}
		}
		else if (command.startsWith("admin_del_drop "))
		{
			int npcId = -1, itemId = -1, category = -1000;
			try
			{
				String[] input = command.substring(15).split(" ");
				if (input.length >= 3)
				{
					npcId = Integer.parseInt(input[0]);
					itemId = Integer.parseInt(input[1]);
					category = Integer.parseInt(input[2]);
				}
			}
			catch (Exception e)
			{
			}
			
			if (npcId > 0)
				deleteDropData(activeChar, npcId, itemId, category);
			else
				activeChar.sendMessage("Usage: //del_drop <npc_id> <item_id> <category>");
		}
		
		return true;
	}
	
	private void editShopItem(L2PcInstance activeChar, String[] args)
	{
		int tradeListID = Integer.parseInt(args[1]);
		int itemID = Integer.parseInt(args[2]);
		L2TradeList tradeList = TradeController.getInstance().getBuyList(tradeListID);
		
		L2Item item = ItemTable.getInstance().getTemplate(itemID);
		if (tradeList.getPriceForItemId(itemID) < 0)
		{
			return;
		}
		
		if (args.length > 3)
		{
			long price = Long.parseLong(args[3]);
			int order = findOrderTradeList(itemID, tradeList.getPriceForItemId(itemID), tradeListID);
			
			tradeList.replaceItem(itemID, Long.parseLong(args[3]));
			updateTradeList(itemID, price, tradeListID, order);
			
			activeChar.sendMessage("Updated price for " + item.getName() + " in Trade List " + tradeListID);
			showShopList(activeChar, tradeListID, 1);
			return;
		}
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);

                final String replyMSG = StringUtil.concat(
                        "<html><title>Merchant Shop Item Edit</title>" +
                        "<body>" +
                        "<br>Edit an entry in merchantList." +
                        "<br>Editing Item: ",
                        item.getName(),
                        "<table>" +
                        "<tr><td width=100>Property</td><td width=100>Edit Field</td><td width=100>Old Value</td></tr>" +
                        "<tr><td><br></td><td></td></tr>" +
                        "<tr><td>Price</td><td><edit var=\"price\" width=80></td><td>",
                        String.valueOf(tradeList.getPriceForItemId(itemID)),
                        "</td></tr>" +
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"Save\" action=\"bypass -h admin_editShopItem ",
                        String.valueOf(tradeListID),
                        " ",
                        String.valueOf(itemID),
                        " $price\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "<br><button value=\"Back\" action=\"bypass -h admin_showShopList ",
                        String.valueOf(tradeListID),
                        " 1\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "</center>" +
                        "</body></html>"
                        );
		
		adminReply.setHtml(replyMSG);
		activeChar.sendPacket(adminReply);
	}
	
	private void delShopItem(L2PcInstance activeChar, String[] args)
	{
		int tradeListID = Integer.parseInt(args[1]);
		int itemID = Integer.parseInt(args[2]);
		L2TradeList tradeList = TradeController.getInstance().getBuyList(tradeListID);
		
		if (tradeList.getPriceForItemId(itemID) < 0)
			return;
		
		if (args.length > 3)
		{
			int order = findOrderTradeList(itemID, tradeList.getPriceForItemId(itemID), tradeListID);
			
			tradeList.removeItem(itemID);
			deleteTradeList(tradeListID, order);
			
			activeChar.sendMessage("Deleted " + ItemTable.getInstance().getTemplate(itemID).getName() + " from Trade List " + tradeListID);
			showShopList(activeChar, tradeListID, 1);
			return;
		}
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);

                final String replyMSG = StringUtil.concat(
                        "<html><title>Merchant Shop Item Delete</title>" +
                        "<body>" +
                        "<br>Delete entry in merchantList." +
                        "<br>Item to Delete: ",
                        ItemTable.getInstance().getTemplate(itemID).getName(),
                        "<table>" +
                        "<tr><td width=100>Property</td><td width=100>Value</td></tr>" +
                        "<tr><td><br></td><td></td></tr>" +
                        "<tr><td>Price</td><td>",
                        String.valueOf(tradeList.getPriceForItemId(itemID)),
                        "</td></tr>" +
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"Confirm\" action=\"bypass -h admin_delShopItem ",
                        String.valueOf(tradeListID),
                        " ",
                        String.valueOf(itemID),
                        " 1\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "<br><button value=\"Back\" action=\"bypass -h admin_showShopList ",
                        String.valueOf(tradeListID),
                        " 1\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">",
                        "</center>" +
                        "</body></html>"
                        );
		
		adminReply.setHtml(replyMSG);
		activeChar.sendPacket(adminReply);
	}
	
	private void addShopItem(L2PcInstance activeChar, String[] args)
	{
		int tradeListID = Integer.parseInt(args[1]);
		
		L2TradeList tradeList = TradeController.getInstance().getBuyList(tradeListID);
		if (tradeList == null)
		{
			activeChar.sendMessage("TradeList not found!");
			return;
		}
		
		if (args.length > 3)
		{
			int order = tradeList.getItems().size() + 1; // last item order + 1
			int itemID = Integer.parseInt(args[2]);
			long price = Long.parseLong(args[3]);
			
			L2TradeItem newItem = new L2TradeItem(tradeListID, itemID);
			newItem.setPrice(price);
			newItem.setMaxCount(-1);
			tradeList.addItem(newItem);
			storeTradeList(itemID, price, tradeListID, order);
			
			activeChar.sendMessage("Added " + ItemTable.getInstance().getTemplate(itemID).getName() + " to Trade List " + tradeList.getListId());
			showShopList(activeChar, tradeListID, 1);
			return;
		}
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);

                final String replyMSG = StringUtil.concat(
                        "<html><title>Merchant Shop Item Add</title>" +
                        "<body>" +
                        "<br>Add a new entry in merchantList." +
                        "<table>" +
                        "<tr><td width=100>Property</td><td>Edit Field</td></tr>" +
                        "<tr><td><br></td><td></td></tr>" +
                        "<tr><td>ItemID</td><td><edit var=\"itemID\" width=80></td></tr>" +
                        "<tr><td>Price</td><td><edit var=\"price\" width=80></td></tr>" +
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"Save\" action=\"bypass -h admin_addShopItem ",
                        String.valueOf(tradeListID),
                        " $itemID $price\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "<br><button value=\"Back\" action=\"bypass -h admin_showShopList ",
                        String.valueOf(tradeListID),
                        " 1\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "</center>" +
                        "</body></html>"
                        );
		
		adminReply.setHtml(replyMSG);
		activeChar.sendPacket(adminReply);
	}
	
	private void showShopList(L2PcInstance activeChar, int tradeListID, int page)
	{
		L2TradeList tradeList = TradeController.getInstance().getBuyList(tradeListID);
		if (page > tradeList.getItems().size() / PAGE_LIMIT + 1 || page < 1)
			return;
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		adminReply.setHtml(itemListHtml(tradeList, page));
		activeChar.sendPacket(adminReply);
		
	}
	
	private String itemListHtml(L2TradeList tradeList, int page)
	{
		final StringBuilder replyMSG = new StringBuilder();

                StringUtil.append(replyMSG,
                        "<html><title>Merchant Shop List Page: ",
                        String.valueOf(page),
                        "</title>" +
                        "<body>" +
                        "<br>Edit, add or delete entries in a merchantList." +
                        "<table>" +
                        "<tr><td width=150>Item Name</td><td width=60>Price</td><td width=40>Delete</td></tr>"
                        );
		
		int start = ((page - 1) * PAGE_LIMIT);
		int end = Math.min(((page - 1) * PAGE_LIMIT) + (PAGE_LIMIT - 1), tradeList.getItems().size() - 1);
		for (L2TradeItem item : tradeList.getItems(start, end + 1))
		{
                    StringUtil.append(replyMSG,
                            "<tr><td><a action=\"bypass -h admin_editShopItem ",
                            String.valueOf(tradeList.getListId()),
                            " ",
                            String.valueOf(item.getItemId()),
                            "\">",
                            ItemTable.getInstance().getTemplate(item.getItemId()).getName(),
                            "</a></td>" +
                            "<td>",
                            String.valueOf(item.getPrice()),
                            "</td>" +
                            "<td><button value=\"Del\" action=\"bypass -h admin_delShopItem ",
                            String.valueOf(tradeList.getListId()),
                            " ",
                            String.valueOf(item.getItemId()),
                            "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>" +
                            "</tr>"
                            );
		}//*/
                StringUtil.append(replyMSG, "<tr>");
		int min = 1;
		int max = tradeList.getItems().size() / PAGE_LIMIT + 1;
		if (page > 1)
		{
                    StringUtil.append(replyMSG,
                            "<td><button value=\"Page",
                            String.valueOf(page - 1),
                            "\" action=\"bypass -h admin_showShopList ",
                            String.valueOf(tradeList.getListId()),
                            " ",
                            String.valueOf(page - 1),
                            "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>"
                            );
		}
		if (page < max)
		{
			if (page <= min) {
                            StringUtil.append(replyMSG, "<td></td>");
                        }

                        StringUtil.append(replyMSG,
                                "<td><button value=\"Page",
                                String.valueOf(page + 1),
                                "\" action=\"bypass -h admin_showShopList ",
                                String.valueOf(tradeList.getListId()),
                                " ",
                                String.valueOf(page + 1),
                                "\" width=40 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>"
                                );
		}

                StringUtil.append(replyMSG,
                        "</tr><tr><td>.</td></tr>" +
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"Add\" action=\"bypass -h admin_addShopItem ",
                        String.valueOf(tradeList.getListId()),
                        "\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "<button value=\"Close\" action=\"bypass -h admin_close_window\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "</center></body></html>"
                        );
		
		return replyMSG.toString();
	}
	
	private void showShop(L2PcInstance activeChar, int merchantID)
	{
		List<L2TradeList> tradeLists = getTradeLists(merchantID);
		if (tradeLists == null)
		{
			activeChar.sendMessage("Unknown npc template Id: " + merchantID);
			return;
		}
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		
		final StringBuilder replyMSG = new StringBuilder();
                StringUtil.append(replyMSG,
                        "<html><title>Merchant Shop Lists</title>" +
                        "<body>"
                        );

                if (activeChar.getTarget() instanceof L2MerchantInstance)
		{
			String mpcName = ((L2MerchantInstance) activeChar.getTarget()).getMpc().getName();
                        StringUtil.append(replyMSG,
                                "<br>NPC: ",
                                activeChar.getTarget().getName(),
                                "<br>Price Config: ",
                                mpcName);
		}

                StringUtil.append(replyMSG,
                        "<br>Select a list to view" +
                        "<table>" +
                        "<tr><td>Mecrchant List ID</td></tr>"
                        );
		
		for (L2TradeList tradeList : tradeLists)
		{
			if (tradeList != null) {
                            StringUtil.append(replyMSG,
                                    "<tr><td><a action=\"bypass -h admin_showShopList ",
                                    String.valueOf(tradeList.getListId()),
                                    " 1\">Trade List ",
                                    String.valueOf(tradeList.getListId()),
                                    "</a></td></tr>"
                                    );
                        }
		}

                StringUtil.append(replyMSG,
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"Close\" action=\"bypass -h admin_close_window\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "</center></body></html>"
                        );
		
		adminReply.setHtml(replyMSG.toString());
		activeChar.sendPacket(adminReply);
	}
	
	private void storeTradeList(int itemID, long price, int tradeListID, int order)
	{
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement stmt = con.prepareStatement("INSERT INTO merchant_buylists (`item_id`,`price`,`shop_id`,`order`) VALUES (?,?,?,?)");
			stmt.setInt(1, itemID);
			stmt.setLong(2, price);
			stmt.setInt(3, tradeListID);
			stmt.setInt(4, order);
			stmt.execute();
			stmt.close();
		}
		catch (SQLException esql)
		{
			esql.printStackTrace();
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private void updateTradeList(int itemID, long price, int tradeListID, int order)
	{
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement stmt = con.prepareStatement("UPDATE merchant_buylists SET `price` = ? WHERE `shop_id` = ? AND `order` = ?");
			stmt.setLong(1, price);
			stmt.setInt(2, tradeListID);
			stmt.setInt(3, order);
			stmt.execute();
			stmt.close();
		}
		catch (SQLException esql)
		{
			esql.printStackTrace();
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private void deleteTradeList(int tradeListID, int order)
	{
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement stmt = con.prepareStatement("DELETE FROM merchant_buylists WHERE `shop_id` = ? AND `order` = ?");
			stmt.setInt(1, tradeListID);
			stmt.setInt(2, order);
			stmt.execute();
			stmt.close();
		}
		catch (SQLException esql)
		{
			esql.printStackTrace();
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	private int findOrderTradeList(int itemID, long price, int tradeListID)
	{
		Connection con = null;
		int order = 0;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement stmt = con.prepareStatement("SELECT * FROM merchant_buylists WHERE `shop_id` = ? AND `item_id` = ? AND `price` = ?");
			stmt.setInt(1, tradeListID);
			stmt.setInt(2, itemID);
			stmt.setLong(3, price);
			ResultSet rs = stmt.executeQuery();
			rs.first();
			
			order = rs.getInt("order");
			
			stmt.close();
			rs.close();
		}
		catch (SQLException esql)
		{
			esql.printStackTrace();
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
		return order;
	}
	
	private List<L2TradeList> getTradeLists(int merchantID)
	{
		String target = "npc_%objectId%_Buy";
		
		String content = HtmCache.getInstance().getHtm("data/html/merchant/" + merchantID + ".htm");
		
		if (content == null)
		{
			content = HtmCache.getInstance().getHtm("data/html/merchant/30001.htm");
			if (content == null)
				return null;
		}
		
		List<L2TradeList> tradeLists = new FastList<L2TradeList>();
		
		String[] lines = content.split("\n");
		int pos = 0;
		
		for (String line : lines)
		{
			pos = line.indexOf(target);
			if (pos >= 0)
			{
				int tradeListID = Integer.decode((line.substring(pos + target.length() + 1)).split("\"")[0]);
				tradeLists.add(TradeController.getInstance().getBuyList(tradeListID));
			}
		}
		return tradeLists;
	}
	
	public String[] getAdminCommandList()
	{
		return ADMIN_COMMANDS;
	}
	
	private void Show_Npc_Property(L2PcInstance activeChar, L2NpcTemplate npc)
	{
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		String content = HtmCache.getInstance().getHtm("data/html/admin/editnpc.htm");
		
		if (content != null)
		{
			adminReply.setHtml(content);
			adminReply.replace("%npcId%", String.valueOf(npc.npcId));
			adminReply.replace("%templateId%", String.valueOf(npc.idTemplate));
			adminReply.replace("%name%", npc.name);
			adminReply.replace("%serverSideName%", npc.serverSideName == true ? "1" : "0");
			adminReply.replace("%title%", npc.title);
			adminReply.replace("%serverSideTitle%", npc.serverSideTitle == true ? "1" : "0");
			adminReply.replace("%collisionRadius%", String.valueOf(npc.collisionRadius));
			adminReply.replace("%collisionHeight%", String.valueOf(npc.collisionHeight));
			adminReply.replace("%level%", String.valueOf(npc.level));
			adminReply.replace("%sex%", String.valueOf(npc.sex));
			adminReply.replace("%type%", String.valueOf(npc.type));
			adminReply.replace("%attackRange%", String.valueOf(npc.baseAtkRange));
			adminReply.replace("%hp%", String.valueOf(npc.baseHpMax));
			adminReply.replace("%mp%", String.valueOf(npc.baseMpMax));
			adminReply.replace("%hpRegen%", String.valueOf(npc.baseHpReg));
			adminReply.replace("%mpRegen%", String.valueOf(npc.baseMpReg));
			adminReply.replace("%str%", String.valueOf(npc.baseSTR));
			adminReply.replace("%con%", String.valueOf(npc.baseCON));
			adminReply.replace("%dex%", String.valueOf(npc.baseDEX));
			adminReply.replace("%int%", String.valueOf(npc.baseINT));
			adminReply.replace("%wit%", String.valueOf(npc.baseWIT));
			adminReply.replace("%men%", String.valueOf(npc.baseMEN));
			adminReply.replace("%exp%", String.valueOf(npc.rewardExp));
			adminReply.replace("%sp%", String.valueOf(npc.rewardSp));
			adminReply.replace("%pAtk%", String.valueOf(npc.basePAtk));
			adminReply.replace("%pDef%", String.valueOf(npc.basePDef));
			adminReply.replace("%mAtk%", String.valueOf(npc.baseMAtk));
			adminReply.replace("%mDef%", String.valueOf(npc.baseMDef));
			adminReply.replace("%pAtkSpd%", String.valueOf(npc.basePAtkSpd));
			adminReply.replace("%aggro%", String.valueOf(npc.aggroRange));
			adminReply.replace("%mAtkSpd%", String.valueOf(npc.baseMAtkSpd));
			adminReply.replace("%rHand%", String.valueOf(npc.rhand));
			adminReply.replace("%lHand%", String.valueOf(npc.lhand));
			adminReply.replace("%armor%", String.valueOf(npc.armor));
			adminReply.replace("%walkSpd%", String.valueOf(npc.baseWalkSpd));
			adminReply.replace("%runSpd%", String.valueOf(npc.baseRunSpd));
//			adminReply.replace("%factionId%", npc.factionId == null ? "" : npc.factionId);
//			adminReply.replace("%factionRange%", String.valueOf(npc.factionRange));
			adminReply.replace("%isUndead%", npc.isUndead ? "1" : "0");
			adminReply.replace("%absorbLevel%", String.valueOf(npc.absorbLevel));
		}
		else
			adminReply.setHtml("<html><head><body>File not found: data/html/admin/editnpc.htm</body></html>");
		activeChar.sendPacket(adminReply);
	}
	
	private void save_npc_property(L2PcInstance activeChar, String command)
	{
		String[] commandSplit = command.split(" ");
		
		if (commandSplit.length < 4)
			return;
		
		StatsSet newNpcData = new StatsSet();
		
		try
		{
			newNpcData.set("npcId", commandSplit[1]);
			
			String statToSet = commandSplit[2];
			String value = commandSplit[3];
			
			if (commandSplit.length > 4)
			{
				for (int i = 0; i < commandSplit.length - 3; i++)
					value += " " + commandSplit[i + 4];
			}
			
			if (statToSet.equals("templateId"))
				newNpcData.set("idTemplate", Integer.parseInt(value));
			else if (statToSet.equals("name"))
				newNpcData.set("name", value);
			else if (statToSet.equals("serverSideName"))
				newNpcData.set("serverSideName", Integer.parseInt(value));
			else if (statToSet.equals("title"))
				newNpcData.set("title", value);
			else if (statToSet.equals("serverSideTitle"))
				newNpcData.set("serverSideTitle", Integer.parseInt(value) == 1 ? 1 : 0);
			else if (statToSet.equals("collisionRadius"))
				newNpcData.set("collision_radius", Integer.parseInt(value));
			else if (statToSet.equals("collisionHeight"))
				newNpcData.set("collision_height", Integer.parseInt(value));
			else if (statToSet.equals("level"))
				newNpcData.set("level", Integer.parseInt(value));
			else if (statToSet.equals("sex"))
			{
				int intValue = Integer.parseInt(value);
				newNpcData.set("sex", intValue == 0 ? "male" : intValue == 1 ? "female" : "etc");
			}
			else if (statToSet.equals("type"))
			{
				Class.forName("com.l2jserver.gameserver.model.actor.instance." + value + "Instance");
				newNpcData.set("type", value);
			}
			else if (statToSet.equals("attackRange"))
				newNpcData.set("attackrange", Integer.parseInt(value));
			else if (statToSet.equals("hp"))
				newNpcData.set("hp", Integer.parseInt(value));
			else if (statToSet.equals("mp"))
				newNpcData.set("mp", Integer.parseInt(value));
			else if (statToSet.equals("hpRegen"))
				newNpcData.set("hpreg", Integer.parseInt(value));
			else if (statToSet.equals("mpRegen"))
				newNpcData.set("mpreg", Integer.parseInt(value));
			else if (statToSet.equals("str"))
				newNpcData.set("str", Integer.parseInt(value));
			else if (statToSet.equals("con"))
				newNpcData.set("con", Integer.parseInt(value));
			else if (statToSet.equals("dex"))
				newNpcData.set("dex", Integer.parseInt(value));
			else if (statToSet.equals("int"))
				newNpcData.set("int", Integer.parseInt(value));
			else if (statToSet.equals("wit"))
				newNpcData.set("wit", Integer.parseInt(value));
			else if (statToSet.equals("men"))
				newNpcData.set("men", Integer.parseInt(value));
			else if (statToSet.equals("exp"))
				newNpcData.set("exp", Integer.parseInt(value));
			else if (statToSet.equals("sp"))
				newNpcData.set("sp", Integer.parseInt(value));
			else if (statToSet.equals("pAtk"))
				newNpcData.set("patk", Integer.parseInt(value));
			else if (statToSet.equals("pDef"))
				newNpcData.set("pdef", Integer.parseInt(value));
			else if (statToSet.equals("mAtk"))
				newNpcData.set("matk", Integer.parseInt(value));
			else if (statToSet.equals("mDef"))
				newNpcData.set("mdef", Integer.parseInt(value));
			else if (statToSet.equals("pAtkSpd"))
				newNpcData.set("atkspd", Integer.parseInt(value));
			else if (statToSet.equals("aggro"))
				newNpcData.set("aggro", Integer.parseInt(value));
			else if (statToSet.equals("mAtkSpd"))
				newNpcData.set("matkspd", Integer.parseInt(value));
			else if (statToSet.equals("rHand"))
				newNpcData.set("rhand", Integer.parseInt(value));
			else if (statToSet.equals("lHand"))
				newNpcData.set("lhand", Integer.parseInt(value));
			else if (statToSet.equals("armor"))
				newNpcData.set("armor", Integer.parseInt(value));
			else if (statToSet.equals("runSpd"))
				newNpcData.set("runspd", Integer.parseInt(value));
			else if (statToSet.equals("factionId"))
				newNpcData.set("faction_id", value);
			else if (statToSet.equals("factionRange"))
				newNpcData.set("faction_range", Integer.parseInt(value));
			else if (statToSet.equals("isUndead"))
				newNpcData.set("isUndead", Integer.parseInt(value) == 1 ? 1 : 0);
			else if (statToSet.equals("absorbLevel"))
			{
				int intVal = Integer.parseInt(value);
				newNpcData.set("absorb_level", intVal < 0 ? 0 : intVal > 12 ? 0 : intVal);
			}
		}
		catch (Exception e)
		{
			_log.warning("Error saving new npc value: " + e);
		}
		
		NpcTable.getInstance().saveNpc(newNpcData);
		
		int npcId = newNpcData.getInteger("npcId");
		
		NpcTable.getInstance().reloadNpc(npcId);
		Show_Npc_Property(activeChar, NpcTable.getInstance().getTemplate(npcId));
	}
	
	private void showNpcDropList(L2PcInstance activeChar, int npcId)
	{
if (! L2J_JP) {{
		L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
		if (npcData == null)
		{
			activeChar.sendMessage("unknown npc template id" + npcId);
			return;
		}
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		
		final StringBuilder replyMSG = new StringBuilder(2900);
                replyMSG.append("<html><title>Drop manage</title>"
                	+ "<body>NPC: ");
                replyMSG.append(npcData.name);
                replyMSG.append(" [");
                replyMSG.append(npcData.npcId);
		replyMSG.append(']');
		replyMSG.append("<br>Notes: click[drop_id]to show the detail of drop data,click[del] to delete the drop data!"
			+ "<table>"
			+ "<tr><td>npc_id itemId category</td><td>item[id]</td><td>type</td><td>del</td></tr>");
		
		if (npcData.getDropData() != null)
			for (L2DropCategory cat : npcData.getDropData())
				for (L2DropData drop : cat.getAllDrops())
				{
					replyMSG.append("<tr><td><a action=\"bypass -h admin_edit_drop ");
                                        replyMSG.append(npcData.npcId);
                                        replyMSG.append(' ');
                                        replyMSG.append(drop.getItemId());
                                        replyMSG.append(' ');
                                        replyMSG.append(cat.getCategoryType());
                                        replyMSG.append("\">");
                                        replyMSG.append(npcData.npcId);
                                        replyMSG.append(' ');
                                        replyMSG.append(drop.getItemId());
                                        replyMSG.append(cat.getCategoryType());
                                        replyMSG.append("</a></td><td>");
                                        replyMSG.append(ItemTable.getInstance().getTemplate(drop.getItemId()).getName());
                                        replyMSG.append('[');
                                        replyMSG.append(drop.getItemId());
                                        replyMSG.append("]</td><td>");
                                        replyMSG.append((drop.isQuestDrop() ? "Q" : (cat.isSweep() ? "S" : "D")));
                                        replyMSG.append("</td><td><a action=\"bypass -h admin_del_drop ");
                                        replyMSG.append(npcData.npcId);
                                        replyMSG.append(' ');
                                        replyMSG.append(drop.getItemId());
                                        replyMSG.append(' ');
                                        replyMSG.append(cat.getCategoryType());
                                        replyMSG.append("\">del</a></td></tr>");
				}
		
		replyMSG.append("</table>"
			+ "<center><br><br><br>"
			+ "<button value=\"Add DropData\" action=\"bypass -h admin_add_drop ");
                replyMSG.append(npcId);
                replyMSG.append("\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">");
		replyMSG.append("<button value=\"Close\" action=\"bypass -h admin_close_window\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">"
			+ "</center></body></html>");
		
		adminReply.setHtml(replyMSG.toString());
		activeChar.sendPacket(adminReply);
		
}}
	}
	
	private void showEditDropData(L2PcInstance activeChar, int npcId, int itemId, int category)
	{
		Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("SELECT mobId, itemId, min, max, category, chance FROM droplist WHERE mobId = ? AND itemId = ? AND category = ?");
			statement.setInt(1, npcId);
			statement.setInt(2, itemId);
			statement.setInt(3, category);
			ResultSet dropData = statement.executeQuery();
			
			NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
			
			final StringBuilder replyMSG = new StringBuilder();
                        replyMSG.append("<html><title>Detail of dropdata</title>"
							+ "<body>NPC: ");
                        replyMSG.append(npcId);
                        replyMSG.append(" / ITEM: ");
                        replyMSG.append(itemId);
                        replyMSG.append(" / CATEGORY: ");
                        replyMSG.append(category);
                        replyMSG.append("<BR>");
			
			if (dropData.next())
			{
				replyMSG.append("<table>"
					+ "<tr><td>Appertain of NPC</td><td>");
                                replyMSG.append(NpcTable.getInstance().getTemplate(dropData.getInt("mobId")).name);
                                replyMSG.append("</td></tr>");
				replyMSG.append("<tr><td>ItemName</td><td>");
                                replyMSG.append(ItemTable.getInstance().getTemplate(dropData.getInt("itemId")).getName());
                             // replyMSG.append('(');
                             // replyMSG.append(dropData.getInt("itemId"));
                                replyMSG.append("</td></tr>");
				replyMSG.append("<tr><td>Category</td><td>").append(((category == -1) ? "sweep" : Integer.toString(category))).append("</td></tr>"
					+ "<tr><td>MIN(").append(dropData.getInt("min")).append(")</td><td><edit var=\"min\" width=80></td></tr>"
					+ "<tr><td>MAX(").append(dropData.getInt("max")).append(")</td><td><edit var=\"max\" width=80></td></tr>"
					+ "<tr><td>CHANCE(").append(dropData.getInt("chance")).append(")</td><td><edit var=\"chance\" width=80></td></tr>"
					+ "</table>"
				
					+ "<center><br><br><br>"
					+ "<button value=\"Save Modify\" action=\"bypass -h admin_edit_drop ").append(npcId).append(' ').append(itemId).append(' ').append(category)
						.append(" $min $max $chance\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">");
				replyMSG.append("<br><button value=\"DropList\" action=\"bypass -h admin_show_droplist ").append(dropData.getInt("mobId")).append("\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">"
					+ "</center>");
			}
			
			dropData.close();
			statement.close();
			
			replyMSG.append("</body></html>");
			adminReply.setHtml(replyMSG.toString());
			
			activeChar.sendPacket(adminReply);
		}
		catch (Exception e)
		{
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
	}
	
	private void showAddDropData(L2PcInstance activeChar, L2NpcTemplate npcData)
	{
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);

                final String replyMSG = StringUtil.concat(
                        "<html><title>Add dropdata</title>" +
                        "<body>NPC: " ,
                        npcData.name,
                        " [",
                        String.valueOf(npcData.npcId),
                        "]" +
                        "<table>" +
                        "<tr><td>Item-Id</td><td><edit var=\"itemId\" width=80></td></tr>" +
                        "<tr><td>MIN</td><td><edit var=\"min\" width=80></td></tr>" +
                        "<tr><td>MAX</td><td><edit var=\"max\" width=80></td></tr>" +
                        "<tr><td>CATEGORY(sweep=-1)</td><td><edit var=\"category\" width=80></td></tr>" +
                        "<tr><td>CHANCE(0-1000000)</td><td><edit var=\"chance\" width=80></td></tr>" +
                        "</table>" +
                        "<center><br><br><br>" +
                        "<button value=\"SAVE\" action=\"bypass -h admin_add_drop ",
                        String.valueOf(npcData.npcId),
                        " $itemId $category $min $max $chance\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "<br><button value=\"DropList\" action=\"bypass -h admin_show_droplist ",
                        String.valueOf(npcData.npcId),
                        "\"  width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                        "</center>" +
                        "</body></html>"
                        );
		adminReply.setHtml(replyMSG);
		
		activeChar.sendPacket(adminReply);
	}
	
	private void updateDropData(L2PcInstance activeChar, int npcId, int itemId, int min, int max, int category, int chance)
	{
		Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("UPDATE droplist SET min=?, max=?, chance=? WHERE mobId=? AND itemId=? AND category=?");
			statement.setInt(1, min);
			statement.setInt(2, max);
			statement.setInt(3, chance);
			statement.setInt(4, npcId);
			statement.setInt(5, itemId);
			statement.setInt(6, category);
			
			statement.execute();
			statement.close();
			
			PreparedStatement statement2 = con.prepareStatement("SELECT mobId FROM droplist WHERE mobId=? AND itemId=? AND category=?");
			statement2.setInt(1, npcId);
			statement2.setInt(2, itemId);
			statement2.setInt(3, category);
			
			ResultSet npcIdRs = statement2.executeQuery();
			if (npcIdRs.next())
				npcId = npcIdRs.getInt("mobId");
			npcIdRs.close();
			statement2.close();
			
			if (npcId > 0)
			{
				reLoadNpcDropList(npcId);
				
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
                                final String replyMSG = StringUtil.concat(
                                        "<html><title>Drop data modify complete!</title>" +
                                        "<body>" +
                                        "<center><button value=\"DropList\" action=\"bypass -h admin_show_droplist ",
                                        String.valueOf(npcId),
                                        "\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></center>" +
                                        "</body></html>"
                                        );
				
				adminReply.setHtml(replyMSG);
				activeChar.sendPacket(adminReply);
			}
			else
				activeChar.sendMessage("unknown error!");
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
	}
	
	private void addDropData(L2PcInstance activeChar, int npcId, int itemId, int min, int max, int category, int chance)
	{
		Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("INSERT INTO droplist(mobId, itemId, min, max, category, chance) values(?,?,?,?,?,?)");
			statement.setInt(1, npcId);
			statement.setInt(2, itemId);
			statement.setInt(3, min);
			statement.setInt(4, max);
			statement.setInt(5, category);
			statement.setInt(6, chance);
			statement.execute();
			statement.close();
			
			reLoadNpcDropList(npcId);
			
			NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
                        final String replyMSG = StringUtil.concat(
                                "<html><title>Add drop data complete!</title>" +
                                "<body>" +
                                "<center><button value=\"Continue add\" action=\"bypass -h admin_add_drop ",
                                String.valueOf(npcId),
                                "\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                                "<br><br><button value=\"DropList\" action=\"bypass -h admin_show_droplist ",
                                String.valueOf(npcId),
                                "\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\">" +
                                "</center></body></html>"
                                );
			
			adminReply.setHtml(replyMSG);
			activeChar.sendPacket(adminReply);
		}
		catch (Exception e)
		{
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
	}
	
	private void deleteDropData(L2PcInstance activeChar, int npcId, int itemId, int category)
	{
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			if (npcId > 0)
			{
				PreparedStatement statement2 = con.prepareStatement("DELETE FROM droplist WHERE mobId=? AND itemId=? AND category=?");
				statement2.setInt(1, npcId);
				statement2.setInt(2, itemId);
				statement2.setInt(3, category);
				statement2.execute();
				statement2.close();
				
				reLoadNpcDropList(npcId);
				
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
                                final String replyMSG = StringUtil.concat(
                                        "<html><title>Delete drop data complete</title>" +
                                        "<body>NPC: ",
                                        String.valueOf(npcId),
                                        " / ITEM: ",
                                        String.valueOf(itemId),
                                        " / CATEGORY: ",
                                        String.valueOf(category),
                                        "<center><button value=\"DropList\" action=\"bypass -h admin_show_droplist " + npcId + "\" width=100 height=15 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></center>" +
                                        "</body></html>"
                                        );
				
				adminReply.setHtml(replyMSG);
				activeChar.sendPacket(adminReply);
				
			}
		}
		catch (Exception e)
		{
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
		
	}
	
	private void reLoadNpcDropList(int npcId)
	{
		L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
		if (npcData == null)
			return;
		
		// reset the drop lists
		npcData.clearAllDropData();
		
		// get the drops
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			L2DropData dropData = null;
			
			npcData.clearAllDropData();
			
			PreparedStatement statement = con.prepareStatement("SELECT " + L2DatabaseFactory.getInstance().safetyString(new String[]
			{
				"mobId", "itemId", "min", "max", "category", "chance"
			}) + " FROM droplist WHERE mobId=?");
			statement.setInt(1, npcId);
			ResultSet dropDataList = statement.executeQuery();
			
			while (dropDataList.next())
			{
				dropData = new L2DropData();
				
				dropData.setItemId(dropDataList.getInt("itemId"));
				dropData.setMinDrop(dropDataList.getInt("min"));
				dropData.setMaxDrop(dropDataList.getInt("max"));
				dropData.setChance(dropDataList.getInt("chance"));
				
				int category = dropDataList.getInt("category");
				// [L2J_JP ADD]
				dropData.setCategoryType(category);
				npcData.addDropData(dropData, category);
			}
			dropDataList.close();
			statement.close();
		}
		catch (Exception e)
		{
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
	}
	
	// [L2J_JP ADD]
	private void showNpcDropList(L2PcInstance admin, int npcId, int page)
	{
if (L2J_JP) {{
		L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
		if (npcData == null)
		{
			admin.sendMessage("unknown npc template id" + npcId);
			return;
		}
		
		// -----------------------------------------
		// カテゴリタイプ込みの drops を連結
		FastList<L2DropData> drops = new FastList<L2DropData>();
		FastList<L2DropCategory> _categories = new FastList<L2DropCategory>();
		_categories = npcData.getDropData();
		if (_categories != null)
			for (L2DropCategory cur_cat : _categories)
				drops.addAll(cur_cat.getAllDrops());
		
		// -----------------------------------------
		// drops を カテゴリタイプ, アイテムID 順にソート
		Collections.sort(drops, new Comparator<L2DropData>() {
			public int compare(L2DropData p1, L2DropData p2)
			{
				int ret = p1.getCategoryType() - p2.getCategoryType();
				if (ret == 0)
					ret = p1.getItemId() - p2.getItemId();
				return ret;
			}
		});
		
		// -----------------------------------------
		// ページ設定
		final int DROPS_PAGE_LIMIT = 10; // 1ページの最大項目数
		final int minPage = 0;
		final int maxPage = Math.max(0, (drops.size() - 1 + DROPS_PAGE_LIMIT) / DROPS_PAGE_LIMIT - 1);
		if (page > maxPage)
			page = maxPage;
		final int dropsStart = DROPS_PAGE_LIMIT * page;
		final int dropsEnd = Math.min(dropsStart + DROPS_PAGE_LIMIT, drops.size()) - 1;
		
		// -----------------------------------------
		// HTML部生成
		StringBuilder replyMSG = new StringBuilder("<html><title>ドロップ リスト</title>"
			+ "<body>NPC: ").append(npcData.name).append(" [").append(npcId).append("]"
				+ "<BR1>(").append(drops.size()).append(" drops)"
				+ "<br>メモ：[アイテム]クリックでその詳細を表示、[消]クリックでリストから削除、一撃で消えるので注意。");
		
		replyMSG.append("<center><table width=270><tr>");
		for (int x = minPage; x <= maxPage; x++)
		{
			int pagenr = x + 1;
			if (page == x) {
				replyMSG.append("<td>Page ").append(pagenr).append("</td>");
			} else {
				replyMSG.append("<td><a action=\"bypass -h admin_show_droplist ").append(npcData.npcId).append(' ')
						.append(x).append("\">Page ").append(pagenr).append("</a></td>");
			}
		}
		replyMSG.append("</tr></table></center>"
		
			+ "T&nbsp;:&nbsp;D=drop, S=sweep<br>"
			+ "<table width=280 BORDER=1 CELLSPACING=0>"
			+ "<tr><td width=235>アイテム&nbsp;[category][itemid]</td><td width=15>T</td><td width=20></td></tr>");
		
		for (int index = dropsStart; index <= dropsEnd; index++)
		{
			L2DropData drop = drops.get(index);
			// クエストドロップは L2DropCategory.addDropData で弾かれるが念のため対象外に
			if (!drop.isQuestDrop())
			{
				replyMSG.append("<tr><td>"
						+ "<a action=\"bypass -h admin_edit_drop ")
						.append(npcData.npcId)
						.append(' ').append(drop.getItemId())
						.append(' ').append(drop.getCategoryType())
						.append("\">")
						.append(ItemTable.getInstance().getTemplate(drop.getItemId()).getName())
						.append("&nbsp;[").append(drop.getCategoryType()).append("]"
						+ "&nbsp;[").append(drop.getItemId()).append("]"
						+ "</a></td>"
						+ "<td>").append((drop.isSweep() ? "S" : "D"))
						.append("</td><td>"
						+ "<a action=\"bypass -h admin_del_drop ")
						.append(npcData.npcId)
						.append(' ').append(drop.getItemId())
						.append(' ').append(drop.getCategoryType())
						.append("\">消</a></td></tr>"
						);
			}
		}
		
	    replyMSG.append("</table>"
		
			+ "<center><br><br><br>"
	    	+ "<button value=\"ドロップ追加\" action=\"bypass -h admin_add_drop ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
	    	+ "<button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
//	    replyMSG.append("<button value=\"Close\" action=\"bypass -h admin_edit_npc " + npcData.npcId + "\" width=100 height=15 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">");
	    	+ "</center></body></html>");
	    
	    // -----------------------------------------
		// 終了処理
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		adminReply.setHtml(replyMSG.toString());
		admin.sendPacket(adminReply);
}}
	}
	
	// [L2J_JP ADD]
	private void showNpcSkillList(L2PcInstance admin, int npcId, int page)
	{
		L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
		if (npcData == null)
		{
			admin.sendMessage("unknown npc template id" + npcId);
			return;
		}
		
		Map<Integer, L2Skill> skills = npcData.getSkills();
		if (skills == null) skills = new FastMap<Integer, L2Skill>(); //dummy
		
		final int _skillSize = skills.size();
		
		final int SKILL_PAGE_LIMIT = 10;
		final int minPage = 0;
		final int maxPage = Math.max(0, (_skillSize - 1 + SKILL_PAGE_LIMIT) / SKILL_PAGE_LIMIT - 1);
		if (page > maxPage)
			page = maxPage;
		final int skillStart = SKILL_PAGE_LIMIT * page;
		final int skillEnd = Math.min(skillStart + SKILL_PAGE_LIMIT, _skillSize) - 1;
		
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		
		StringBuilder replyMSG = new StringBuilder("<html><title>スキル リスト</title>"
			+ "<body>NPC: ").append(npcData.name).append(" [").append(npcId).append("]"
				+ "<BR1>(").append(_skillSize).append(" skills)"
				+ "<br>メモ：[スキル]クリックでその詳細を表示、"
				+ "[消]クリックでリストから削除、一撃で消えるので注意。"
				+ "<BR1>Raceは表示されません。");
        replyMSG.append("<center><table width=270><tr>");
		for (int x = minPage; x <= maxPage; x++)
		{
			int pagenr = x + 1;
			if (page == x) {
				replyMSG.append("<td>Page ").append(pagenr).append("</td>");
			} else {
				replyMSG.append("<td><a action=\"bypass -h admin_show_skilllist_npc ").append(npcData.npcId).append(' ')
						.append(x).append("\">Page ").append(pagenr).append("</a></td>");
			}
		}
		replyMSG.append("</tr></table></center>"
		
			+ "<table width=280>"
			+ "<tr><td width=230>スキル&nbsp;[id]</td><td width=20>Lv</td><td width=20></td></tr>");
		
		int index = -1;
		for (L2Skill skill : skills.values())
		{
			++index;
			if (index < skillStart) continue;
			if (index > skillEnd) break;
			replyMSG.append("<tr><td><a action=\"bypass -h admin_edit_skill_npc ")
					.append(npcData.npcId).append(' ').append(skill.getId()).append("\">")
					.append(skill.getName()).append("&nbsp;[").append(skill.getId()).append("]"
					+ "</a></td>"
					+ "<td>").append(skill.getLevel()).append("</td>"
					+ "<td><a action=\"bypass -h admin_del_skill_npc ").append(npcData.npcId)
					.append(' ').append(skill.getId()).append("\">消</a></td></tr>");
		}
		
		replyMSG.append("</table>"
		
			+ "<center><br><br><br>"
			+ "<button value=\"スキル追加\" action=\"bypass -h admin_add_skill_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
			+ "<button value=\"ドロップ表示\" action=\"bypass -h admin_show_droplist ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
			+ "</center></body></html>");
		
		adminReply.setHtml(replyMSG.toString());
		admin.sendPacket(adminReply);
	}
	
	// [L2J_JP ADD][JOJO]
	private void showNpcSkillEdit(L2PcInstance admin, int npcId, int skillId)
	{
		java.sql.Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("SELECT npcskills.level, name, description FROM npcskills"
					 + " LEFT JOIN skillname_ja ON (npcskills.skillid=skillname_ja.id AND npcskills.level=skillname_ja.level)"
					 + " WHERE npcid=" + npcId + " AND skillid=" + skillId);
		//	PreparedStatement statement = con.prepareStatement("SELECT npcid, skillid, level FROM npcskills WHERE npcid=" + npcId + " AND skillid=" + skillId);
			ResultSet skillData = statement.executeQuery();
			
			NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
			
			StringBuilder replyMSG = new StringBuilder(1000);
			replyMSG.append("<html><title>スキル詳細</title>"
				+ "<body>NPC: ").append(NpcTable.getInstance().getTemplate(npcId).name).append(" [").append(npcId).append("]<br>");
			
			String description = null;
			if (skillData.next())
			{
				int level = skillData.getInt("level");
				L2Skill skill = SkillTable.getInstance().getInfo(skillId, level);
			//	L2Skill skill = SkillTable.getInstance().getInfo(skillData.getInt("skillid"), skillData.getInt("level"));
				String skillName = skillData.getString("name");
				description = skillData.getString("description");
				
                replyMSG.append("<table>"
					+ "<tr><td>スキル</td><td>").append(skillName).append("</td></tr>"
					+ "<tr><td></td><td>").append(skill.getName()).append("</td></tr>"
					+ "<tr><td>ID</td><td>").append(skillId).append("</td></tr>"
					+ "<tr><td>レベル(").append(level).append(")</td><td><edit var=\"level\" width=50></td></tr>"
					+ "</table>"
				
					+ "<center><br><br><br>"
					+ "<button value=\"更新\" action=\"bypass -h admin_edit_skill_npc ").append(npcId).append(' ').append(skillId).append(" $level\"  width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>");
			}
			replyMSG.append("<center><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>");
			if (description != null && ! description.isEmpty())
				replyMSG.append("description:<table WIDTH=80% bgcolor=333333><tr><td>").append(description).append("</td></tr></table>");
			
			skillData.close();
			statement.close();
			
			replyMSG.append("</body></html>");
			adminReply.setHtml(replyMSG.toString());
			
			admin.sendPacket(adminReply);
		}
		catch (Exception e) { e.printStackTrace(); }
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}
	
	// [L2J_JP ADD]
	private void updateNpcSkillData(L2PcInstance admin, int npcId, int skillId, int level)
	{
		java.sql.Connection con = null;
		
		try
		{
			// skill check
			L2Skill skillData = SkillTable.getInstance().getInfo(skillId, level);
			if (skillData == null)
			{
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
				StringBuilder replyMSG = new StringBuilder("<html><title>スキル更新エラー</title>"
					+ "<body>該当スキルは、指定レベルをサポートしていません。xmlを確認してください。<br>"
					+ "<center><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>"
					+ "</body></html>");
				
				adminReply.setHtml(replyMSG.toString());
				admin.sendPacket(adminReply);
				return;
			}
			
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("UPDATE npcskills SET level=? WHERE npcid=? AND skillid=?");
			statement.setInt(1, level);
			statement.setInt(2, npcId);
			statement.setInt(3, skillId);
			
			statement.execute();
			statement.close();
			
			if (npcId > 0)
			{
				reLoadNpcSkillList(npcId);
				
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
				StringBuilder replyMSG = new StringBuilder("<html><title>スキル更新完了</title>"
					+ "<body>"
					+ "<center><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>"
					+ "</body></html>");
				
				adminReply.setHtml(replyMSG.toString());
				admin.sendPacket(adminReply);
			}
			else
			{
				admin.sendMessage("unknown error!");
			}
			
		}
		catch(Exception e){ e.printStackTrace(); }
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}
	
	// [L2J_JP ADD]
	private void showNpcSkillAdd(L2PcInstance admin, L2NpcTemplate npcData)
	{
		NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
		
		StringBuilder replyMSG = new StringBuilder("<html><title>スキル追加</title>"
			+ "<body>NPC: ").append(npcData.name).append(" [").append(npcData.npcId).append("]"
			+ "<table>"
			+ "<tr><td>SkillId</td><td><edit var=\"skillId\" width=80></td></tr>"
			+ "<tr><td>Level</td><td><edit var=\"level\" width=80></td></tr>"
			+ "</table>"
		
			+ "<center><br><br><br>"
			+ "<button value=\"追加\" action=\"bypass -h admin_add_skill_npc ").append(npcData.npcId).append(" $skillId $level\"  width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
			+ "<br><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcData.npcId).append("\"  width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
			+ "</center>"
			+ "</body></html>");
		adminReply.setHtml(replyMSG.toString());
		
		admin.sendPacket(adminReply);
	}
	
	// [L2J_JP ADD]
	private void addNpcSkillData(L2PcInstance admin, int npcId, int skillId, int level)
	{
		java.sql.Connection con = null;
		
		try
		{
			// skill check
			L2Skill skillData = SkillTable.getInstance().getInfo(skillId, level);
			if (skillData == null)
			{
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
				StringBuilder replyMSG = new StringBuilder("<html><title>スキル追加エラー</title>"
					+ "<body>該当スキルは、指定レベルをサポートしていません。xmlを確認してください。<br>"
					+ "<center><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>"
					+ "</body></html>");
				
				adminReply.setHtml(replyMSG.toString());
				admin.sendPacket(adminReply);
				return;
			}
			
			con = L2DatabaseFactory.getInstance().getConnection();
			
			PreparedStatement statement = con.prepareStatement("INSERT INTO npcskills(npcid, skillid, level) values(?,?,?)");
			statement.setInt(1, npcId);
			statement.setInt(2, skillId);
			statement.setInt(3, level);
			statement.execute();
			statement.close();
			
			reLoadNpcSkillList(npcId);
			
			NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
			StringBuilder replyMSG = new StringBuilder("<html><title>スキル追加完了</title>"
				+ "<body>NPC: ").append(npcId).append(" / SKILL: ").append(skillId).append(" / LEVEL: ").append(level);
			replyMSG.append("<BR><center><button value=\"さらにスキル追加\" action=\"bypass -h admin_add_skill_npc ").append(npcId).append("\" width=130 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
				+ "<br><br><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\">"
				+ "</center></body></html>");
			
			adminReply.setHtml(replyMSG.toString());
			admin.sendPacket(adminReply);
		}
		catch (Exception e) { e.printStackTrace(); }
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}
	
	// [L2J_JP ADD]
	private void deleteNpcSkillData(L2PcInstance admin, int npcId, int skillId)
	{
		java.sql.Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			
			if (npcId > 0)
			{
				PreparedStatement statement2 = con.prepareStatement("DELETE FROM npcskills WHERE npcid=? AND skillid=?");
				statement2.setInt(1, npcId);
				statement2.setInt(2, skillId);
				statement2.execute();
				statement2.close();
				
				reLoadNpcSkillList(npcId);
				
				NpcHtmlMessage adminReply = new NpcHtmlMessage(5);
				StringBuilder replyMSG = new StringBuilder("<html><title>スキル削除完了</title>"
					+ "<body>NPC: ").append(npcId).append(" / SKILL: ").append(skillId);
				replyMSG.append("<center><button value=\"スキル表示\" action=\"bypass -h admin_show_skilllist_npc ").append(npcId).append("\" width=100 height=18 back=\"L2UI_ct1.button_df_down\" fore=\"L2UI_ct1.button_df\"></center>"
					+ "</body></html>");
				
				adminReply.setHtml(replyMSG.toString());
				admin.sendPacket(adminReply);
			}
		}
		catch (Exception e) { e.printStackTrace(); }
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}
	
	// [L2J_JP ADD]
	private void reLoadNpcSkillList(int npcId)
	{
		java.sql.Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection();
			L2NpcTemplate npcData = NpcTable.getInstance().getTemplate(npcId);
			
			L2Skill skillData = null;
			if (npcData.getSkills() != null)
				npcData.getSkills().clear();
			
			// with out race
			String _sql = "SELECT npcid, skillid, level FROM npcskills WHERE npcid=? AND (skillid NOT BETWEEN 4290 AND 4302)";
			
			PreparedStatement statement = con.prepareStatement(_sql);
			statement.setInt(1, npcId);
			ResultSet skillDataList = statement.executeQuery();
			
			int i = 1;
			while (skillDataList.next())
			{
				int idval = skillDataList.getInt("skillid");
				int levelval = skillDataList.getInt("level");
				skillData = SkillTable.getInstance().getInfo(idval, levelval);
				if (skillData != null)
					npcData.addSkill(skillData);
				i++;
			}
			skillDataList.close();
			statement.close();
		}
		catch (Exception e) { e.printStackTrace(); }
		finally
		{
			try { con.close(); } catch (Exception e) {}
		}
	}
}
