/* 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.model.actor.instance;

import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import javolution.text.TextBuilder;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.ai.CtrlIntention;
import com.l2jfrozen.gameserver.controllers.TradeController;
import com.l2jfrozen.gameserver.datatables.sql.ClanTable;
import com.l2jfrozen.gameserver.managers.CastleManager;
import com.l2jfrozen.gameserver.managers.CastleManorManager;
import com.l2jfrozen.gameserver.model.L2Clan;
import com.l2jfrozen.gameserver.model.L2TradeList;
import com.l2jfrozen.gameserver.model.PcInventory;
import com.l2jfrozen.gameserver.model.entity.sevensigns.SevenSigns;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.ActionFailed;
import com.l2jfrozen.gameserver.network.serverpackets.BuyList;
import com.l2jfrozen.gameserver.network.serverpackets.ExShowCropInfo;
import com.l2jfrozen.gameserver.network.serverpackets.ExShowCropSetting;
import com.l2jfrozen.gameserver.network.serverpackets.ExShowManorDefaultInfo;
import com.l2jfrozen.gameserver.network.serverpackets.ExShowSeedInfo;
import com.l2jfrozen.gameserver.network.serverpackets.ExShowSeedSetting;
import com.l2jfrozen.gameserver.network.serverpackets.MyTargetSelected;
import com.l2jfrozen.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.network.serverpackets.ValidateLocation;
import com.l2jfrozen.gameserver.templates.L2NpcTemplate;
import com.l2jfrozen.gameserver.util.Util;

/**
 * Castle Chamberlains implementation used for: - tax rate control - regional manor system control - castle treasure
 * control - ...
 */
public class L2CastleChamberlainInstance extends L2FolkInstance
{
	//    private static Logger _log = Logger.getLogger(L2CastleChamberlainInstance.class.getName());

	protected static final int COND_ALL_FALSE = 0;
	protected static final int COND_BUSY_BECAUSE_OF_SIEGE = 1;
	protected static final int COND_OWNER = 2;

	public L2CastleChamberlainInstance(int objectId, L2NpcTemplate template)
	{
		super(objectId, template);
	}

	@Override
	public void onAction(L2PcInstance player)
	{
		if(!canTarget(player))
			return;

		player.setLastFolkNPC(this);

		// Check if the L2PcInstance already target the L2NpcInstance
		if(this != player.getTarget())
		{
			// Set the target of the L2PcInstance player
			player.setTarget(this);

			// Send a Server->Client packet MyTargetSelected to the L2PcInstance player
			MyTargetSelected my = new MyTargetSelected(getObjectId(), 0);
			player.sendPacket(my);
			my = null;

			// Send a Server->Client packet ValidateLocation to correct the L2NpcInstance position and heading on the client
			player.sendPacket(new ValidateLocation(this));
		}
		else
		{
			// Calculate the distance between the L2PcInstance and the L2NpcInstance
			if(!canInteract(player))
			{
				// Notify the L2PcInstance AI with AI_INTENTION_INTERACT
				player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
			}
			else
			{
				showMessageWindow(player);
			}
		}
		// Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
		player.sendPacket(ActionFailed.STATIC_PACKET);
	}

	@Override
	public void onBypassFeedback(L2PcInstance player, String command)
	{
		// BypassValidation Exploit plug.
		if(player.getLastFolkNPC().getObjectId() != getObjectId())
			return;

		StringTokenizer st = new StringTokenizer(command, " ");
		String actualCommand = st.nextToken(); // Get actual command

		int condition = validateCondition(player);
		if(condition <= COND_ALL_FALSE)
			return;

		if(condition == COND_BUSY_BECAUSE_OF_SIEGE)
			return;
		else if(condition == COND_OWNER)
		{
			String val = "";
			if(st.countTokens() >= 1)
			{
				val = st.nextToken();
			}

			if(actualCommand.equalsIgnoreCase("banish_foreigner"))
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_DISMISS) == L2Clan.CP_CS_DISMISS)
				{
					getCastle().banishForeigners(); // Move non-clan members off castle area
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("list_siege_clans"))
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_MANAGE_SIEGE) == L2Clan.CP_CS_MANAGE_SIEGE)
				{
					getCastle().getSiege().listRegisterClan(player); // List current register clan
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("receive_report"))
			{
				if(player.isClanLeader())
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-report.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					L2Clan clan = ClanTable.getInstance().getClan(getCastle().getOwnerId());
					html.replace("%clanname%", clan.getName());
					html.replace("%clanleadername%", clan.getLeaderName());
					html.replace("%castlename%", getCastle().getName());
					{
						int currentPeriod = SevenSigns.getInstance().getCurrentPeriod();
						switch(currentPeriod)
						{
							case SevenSigns.PERIOD_COMP_RECRUITING:
								html.replace("%ss_event%", "Quest Event Initialization");
								break;
							case SevenSigns.PERIOD_COMPETITION:
								html.replace("%ss_event%", "Competition (Quest Event)");
								break;
							case SevenSigns.PERIOD_COMP_RESULTS:
								html.replace("%ss_event%", "Quest Event Results");
								break;
							case SevenSigns.PERIOD_SEAL_VALIDATION:
								html.replace("%ss_event%", "Seal Validation");
								break;
						}
					}
					{
						int sealOwner1 = SevenSigns.getInstance().getSealOwner(1);
						switch(sealOwner1)
						{
							case SevenSigns.CABAL_NULL:
								html.replace("%ss_avarice%", "Not in Possession");
								break;
							case SevenSigns.CABAL_DAWN:
								html.replace("%ss_avarice%", "Lords of Dawn");
								break;
							case SevenSigns.CABAL_DUSK:
								html.replace("%ss_avarice%", "Revolutionaries of Dusk");
								break;
						}
					}
					{
						int sealOwner2 = SevenSigns.getInstance().getSealOwner(2);
						switch(sealOwner2)
						{
							case SevenSigns.CABAL_NULL:
								html.replace("%ss_gnosis%", "Not in Possession");
								break;
							case SevenSigns.CABAL_DAWN:
								html.replace("%ss_gnosis%", "Lords of Dawn");
								break;
							case SevenSigns.CABAL_DUSK:
								html.replace("%ss_gnosis%", "Revolutionaries of Dusk");
								break;
						}
					}
					{
						int sealOwner3 = SevenSigns.getInstance().getSealOwner(3);
						switch(sealOwner3)
						{
							case SevenSigns.CABAL_NULL:
								html.replace("%ss_strife%", "Not in Possession");
								break;
							case SevenSigns.CABAL_DAWN:
								html.replace("%ss_strife%", "Lords of Dawn");
								break;
							case SevenSigns.CABAL_DUSK:
								html.replace("%ss_strife%", "Revolutionaries of Dusk");
								break;
						}
					}
					player.sendPacket(html);
					clan = null;
					html = null;
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("items"))
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_USE_FUNCTIONS) == L2Clan.CP_CS_USE_FUNCTIONS)
				{
					if(val == "")
						return;

					player.tempInvetoryDisable();

					if(Config.DEBUG)
					{
						_log.fine("Showing chamberlain buylist");
					}
					int buy;
					{
						int castleId = getCastle().getCastleId();
						int circlet = CastleManager.getInstance().getCircletByCastleId(castleId);
						PcInventory s = player.getInventory();
						if(s.getItemByItemId(circlet) == null)
						{
							buy = Integer.parseInt(val + "1");
						}
						else
						{
							buy = Integer.parseInt(val + "2");
						}
					}
					L2TradeList list = TradeController.getInstance().getBuyList(buy);
					if(list != null && list.getNpcId().equals(String.valueOf(getNpcId())))
					{
						BuyList bl = new BuyList(list, player.getAdena(), 0);
						player.sendPacket(bl);
					}
					else
					{
						_log.warning("player: " + player.getName() + " attempting to buy from chamberlain that don't have buylist!");
						_log.warning("buylist id:" + buy);
					}
					list = null;

					player.sendPacket(ActionFailed.STATIC_PACKET);
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("manage_vault"))
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_TAXES) == L2Clan.CP_CS_TAXES)
				{
					String filename = "data/html/chamberlain/chamberlain-vault.htm";
					int amount = 0;
					if(val.equalsIgnoreCase("deposit"))
					{
						try
						{
							amount = Integer.parseInt(st.nextToken());
						}
						catch(NoSuchElementException e)
						{
							if(Config.ENABLE_ALL_EXCEPTIONS)
								e.printStackTrace();
						}
						if(amount > 0 && (long) getCastle().getTreasury() + amount < Integer.MAX_VALUE)
						{
							if(player.reduceAdena("Castle", amount, this, true))
							{
								getCastle().addToTreasuryNoTax(amount);
							}
							else
							{
								sendPacket(new SystemMessage(SystemMessageId.YOU_NOT_ENOUGH_ADENA));
							}
						}
					}
					else if(val.equalsIgnoreCase("withdraw"))
					{
						try
						{
							amount = Integer.parseInt(st.nextToken());
						}
						catch(NoSuchElementException e)
						{
							if(Config.ENABLE_ALL_EXCEPTIONS)
								e.printStackTrace();
						}
						if(amount > 0)
						{
							if(getCastle().getTreasury() < amount)
							{
								filename = "data/html/chamberlain/chamberlain-vault-no.htm";
							}
							else
							{
								if(getCastle().addToTreasuryNoTax(-1 * amount))
								{
									player.addAdena("Castle", amount, this, true);
								}
							}
						}
					}

					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile(filename);
					html.replace("%objectId%", String.valueOf(getObjectId()));
					html.replace("%npcname%", getName());
					html.replace("%tax_income%", Util.formatAdena(getCastle().getTreasury()));
					html.replace("%withdraw_amount%", Util.formatAdena(amount));
					player.sendPacket(html);
					filename = null;
					html = null;
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("manor"))
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_MANOR_ADMIN) == L2Clan.CP_CS_MANOR_ADMIN)
				{
					String filename = "";
					if(CastleManorManager.getInstance().isDisabled())
					{
						filename = "data/html/npcdefault.htm";
					}
					else
					{
						int cmd = Integer.parseInt(val);
						switch(cmd)
						{
							case 0:
								filename = "data/html/chamberlain/manor/manor.htm";
								break;
							// TODO: correct in html's to 1
							case 4:
								filename = "data/html/chamberlain/manor/manor_help00" + st.nextToken() + ".htm";
								break;
							default:
								filename = "data/html/chamberlain/chamberlain-no.htm";
								break;
						}
					}
					if(filename.length() != 0)
					{
						NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
						html.setFile(filename);
						html.replace("%objectId%", String.valueOf(getObjectId()));
						html.replace("%npcname%", getName());
						player.sendPacket(html);
						html = null;
						filename = null;
					}
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(command.startsWith("manor_menu_select"))
			{// input string format:
				// manor_menu_select?ask=X&state=Y&time=X
				if((player.getClanPrivileges() & L2Clan.CP_CS_MANOR_ADMIN) == L2Clan.CP_CS_MANOR_ADMIN)
				{
					if(CastleManorManager.getInstance().isUnderMaintenance())
					{
						player.sendPacket(ActionFailed.STATIC_PACKET);
						player.sendPacket(new SystemMessage(SystemMessageId.THE_MANOR_SYSTEM_IS_CURRENTLY_UNDER_MAINTENANCE));
						return;
					}

					String params = command.substring(command.indexOf("?") + 1);
					StringTokenizer str = new StringTokenizer(params, "&");
					int ask = Integer.parseInt(str.nextToken().split("=")[1]);
					int state = Integer.parseInt(str.nextToken().split("=")[1]);
					int time = Integer.parseInt(str.nextToken().split("=")[1]);

					int castleId;
					if(state == -1)
					{
						castleId = getCastle().getCastleId();
					}
					else
					{
						// info for requested manor
						castleId = state;
					}

					switch(ask)
					{ // Main action
						case 3: // Current seeds (Manor info)
							if(time == 1 && !CastleManager.getInstance().getCastleById(castleId).isNextPeriodApproved())
							{
								player.sendPacket(new ExShowSeedInfo(castleId, null));
							}
							else
							{
								player.sendPacket(new ExShowSeedInfo(castleId, CastleManager.getInstance().getCastleById(castleId).getSeedProduction(time)));
							}
							break;
						case 4: // Current crops (Manor info)
							if(time == 1 && !CastleManager.getInstance().getCastleById(castleId).isNextPeriodApproved())
							{
								player.sendPacket(new ExShowCropInfo(castleId, null));
							}
							else
							{
								player.sendPacket(new ExShowCropInfo(castleId, CastleManager.getInstance().getCastleById(castleId).getCropProcure(time)));
							}
							break;
						case 5: // Basic info (Manor info)
							player.sendPacket(new ExShowManorDefaultInfo());
							break;
						case 7: // Edit seed setup
							if(getCastle().isNextPeriodApproved())
							{
								player.sendPacket(new SystemMessage(SystemMessageId.A_MANOR_CANNOT_BE_SET_UP_BETWEEN_6_AM_AND_8_PM));
							}
							else
							{
								player.sendPacket(new ExShowSeedSetting(getCastle().getCastleId()));
							}
							break;
						case 8: // Edit crop setup
							if(getCastle().isNextPeriodApproved())
							{
								player.sendPacket(new SystemMessage(SystemMessageId.A_MANOR_CANNOT_BE_SET_UP_BETWEEN_6_AM_AND_8_PM));
							}
							else
							{
								player.sendPacket(new ExShowCropSetting(getCastle().getCastleId()));
							}
							break;
					}
					params = null;
					str = null;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("operate_door")) // door control
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_OPEN_DOOR) == L2Clan.CP_CS_OPEN_DOOR)
				{
					if(val != "")
					{
						boolean open = Integer.parseInt(val) == 1;
						while(st.hasMoreTokens())
						{
							getCastle().openCloseDoor(player, Integer.parseInt(st.nextToken()), open);
						}
					}

					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/" + getTemplate().npcId + "-d.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					html.replace("%npcname%", getName());
					player.sendPacket(html);
					html = null;
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-noprivs.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
			else if(actualCommand.equalsIgnoreCase("tax_set")) // tax rates control
			{
				if((player.getClanPrivileges() & L2Clan.CP_CS_TAXES) == L2Clan.CP_CS_TAXES)
				{
					if(val != "")
					{
						getCastle().setTaxPercent(player, Integer.parseInt(val));
					}

					TextBuilder msg = new TextBuilder("<html><body>");
					msg.append(getName() + ":<br>");
					msg.append("Current tax rate: " + getCastle().getTaxPercent() + "%<br>");
					msg.append("<table>");
					msg.append("<tr>");
					msg.append("<td>Change tax rate to:</td>");
					msg.append("<td><edit var=\"value\" width=40><br>");
					msg.append("<button value=\"Adjust\" action=\"bypass -h npc_%objectId%_tax_set $value\" width=80 height=15></td>");
					msg.append("</tr>");
					msg.append("</table>");
					msg.append("</center>");
					msg.append("</body></html>");

					sendHtmlMessage(player, msg.toString());
					msg = null;
					return;
				}
				else
				{
					NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
					html.setFile("data/html/chamberlain/chamberlain-tax.htm");
					html.replace("%objectId%", String.valueOf(getObjectId()));
					html.replace("%tax%", String.valueOf(getCastle().getTaxPercent()));
					player.sendPacket(html);
					html = null;
					return;
				}
			}
		}
		st = null;
		actualCommand = null;
		super.onBypassFeedback(player, command);
	}

	private void sendHtmlMessage(L2PcInstance player, String htmlMessage)
	{
		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
		html.setHtml(htmlMessage);
		html.replace("%objectId%", String.valueOf(getObjectId()));
		html.replace("%npcname%", getName());
		player.sendPacket(html);
		html = null;
	}

	private void showMessageWindow(L2PcInstance player)
	{
		player.sendPacket(ActionFailed.STATIC_PACKET);
		String filename = "data/html/chamberlain/chamberlain-no.htm";

		int condition = validateCondition(player);
		if(condition > COND_ALL_FALSE)
		{
			if(condition == COND_BUSY_BECAUSE_OF_SIEGE)
			{
				filename = "data/html/chamberlain/chamberlain-busy.htm"; // Busy because of siege
			}
			else if(condition == COND_OWNER)
			{
				filename = "data/html/chamberlain/chamberlain.htm"; // Owner message window
			}
		}

		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
		html.setFile(filename);
		html.replace("%objectId%", String.valueOf(getObjectId()));
		html.replace("%npcId%", String.valueOf(getNpcId()));
		html.replace("%npcname%", getName());
		player.sendPacket(html);
		filename = null;
		html = null;
	}

	/*
		private void showVaultWindowDeposit(L2PcInstance player)
		{
			player.sendPacket(ActionFailed.STATIC_PACKET);
			player.setActiveWarehouse(player.getClan().getWarehouse());
			player.sendPacket(new WareHouseDepositList(player, WareHouseDepositList.CLAN)); //Or Castle ??
		}

		private void showVaultWindowWithdraw(L2PcInstance player)
		{
			player.sendPacket(ActionFailed.STATIC_PACKET);
			player.setActiveWarehouse(player.getClan().getWarehouse());
			player.sendPacket(new WareHouseWithdrawalList(player, WareHouseWithdrawalList.CLAN)); //Or Castle ??
		}
	*/
	protected int validateCondition(L2PcInstance player)
	{
		if(getCastle() != null && getCastle().getCastleId() > 0)
		{
			if(player.getClan() != null)
			{
				if(getCastle().getSiege().getIsInProgress())
					return COND_BUSY_BECAUSE_OF_SIEGE; // Busy because of siege
				else if(getCastle().getOwnerId() == player.getClanId()) // Clan owns castle
					return COND_OWNER; // Owner
			}
		}

		return COND_ALL_FALSE;
	}
}
