/*
 * 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 net.sf.l2j.gameserver.network.serverpackets;

import java.util.logging.Logger;

import net.sf.l2j.Config;
import net.sf.l2j.gameserver.cache.HtmCache;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.network.clientpackets.RequestBypassToServer;


/**
 *
 * the HTML parser in the client knowns these standard and non-standard tags and attributes
 * VOLUMN
 * UNKNOWN
 * UL
 * U
 * TT
 * TR
 * TITLE
 * TEXTCODE
 * TEXTAREA
 * TD
 * TABLE
 * SUP
 * SUB
 * STRIKE
 * SPIN
 * SELECT
 * RIGHT
 * PRE
 * P
 * OPTION
 * OL
 * MULTIEDIT
 * LI
 * LEFT
 * INPUT
 * IMG
 * I
 * HTML
 * H7
 * H6
 * H5
 * H4
 * H3
 * H2
 * H1
 * FONT
 * EXTEND
 * EDIT
 * COMMENT
 * COMBOBOX
 * CENTER
 * BUTTON
 * BR
 * BODY
 * BAR
 * ADDRESS
 * A
 * SEL
 * LIST
 * VAR
 * FORE
 * READONL
 * ROWS
 * VALIGN
 * FIXWIDTH
 * BORDERCOLORLI
 * BORDERCOLORDA
 * BORDERCOLOR
 * BORDER
 * BGCOLOR
 * BACKGROUND
 * ALIGN
 * VALU
 * READONLY
 * MULTIPLE
 * SELECTED
 * TYP
 * TYPE
 * MAXLENGTH
 * CHECKED
 * SRC
 * Y
 * X
 * QUERYDELAY
 * NOSCROLLBAR
 * IMGSRC
 * B
 * FG
 * SIZE
 * FACE
 * COLOR
 * DEFFON
 * DEFFIXEDFONT
 * WIDTH
 * VALUE
 * TOOLTIP
 * NAME
 * MIN
 * MAX
 * HEIGHT
 * DISABLED
 * ALIGN
 * MSG
 * LINK
 * HREF
 * ACTION
 *
 *
 * @version $Revision: 1.3.2.1.2.3 $ $Date: 2005/03/27 15:29:57 $
 */
public final class NpcHtmlMessage extends L2GameServerPacket
{
	// d S
	// d is usually 0, S is the html text starting with <html> and ending with </html>
	//
	private static final String _S__1B_NPCHTMLMESSAGE = "[S] 19 NpcHtmlMessage";
	private static Logger _log = Logger.getLogger(RequestBypassToServer.class.getName());
	private int _npcObjId;
	private String _html;
	private int _itemId = 0;
	
	/**
	 * 
	 * @param npcObjId
	 * @param text
	 * @param itemId
	 */
	public NpcHtmlMessage(int npcObjId, int itemId)
	{
		_npcObjId = npcObjId;
		_itemId = itemId;
	}

	/**
	 * @param _characters
	 */
	public NpcHtmlMessage(int npcObjId, String text)
	{
		_npcObjId = npcObjId;
		setHtml(text);
	}

	public NpcHtmlMessage(int npcObjId)
	{
		_npcObjId = npcObjId;
	}

	@Override
	public void runImpl()
	{
		if (Config.BYPASS_VALIDATION)
			buildBypassCache(getClient().getActiveChar());
	}

	public void setHtml(String text)
	{
        if(text.length() > 8192)
		{
			_log.warning("Html is too long! this will crash the client!");
			_html = "<html><body>Html was too long</body></html>";
			return;
		}
		_html = text; // html code must not exceed 8192 bytes
	}

	public boolean setFile(String path)
	{
        String content = HtmCache.getInstance().getHtm(path);

		if (content == null)
		{
			setHtml("<html><body>My Text is missing:<br>"+path+"</body></html>");
			_log.warning("missing html page "+path);
			return false;
		}

        setHtml(content);
        return true;
	}

	private char[] _ca = null; private int _count;	//XXX:[JOJO]
	public int replace(CharSequence token, CharSequence value)
	{
		//XXX:[JOJO]
		int result = 0;
		if (_ca == null) {
			_count = _html.length();
			_ca = new char[_count * 2];
			_html.getChars(0, _count, _ca, 0);
		}
		final char first = token.charAt(0);
		final int token_length = token.length();
		final int value_length = value.length();
		for (int start = 0, end; ; start += value_length) {
			indexOf: {
				int max = _count - token_length;
				unko:
				for (; start < max; start++) {
					if (_ca[start] == first) {
						end = start + 1;
						int i = 1;
						while (i < token_length)
							if (_ca[end++] != token.charAt(i++))
								continue unko;
						/*assert(end == start + token_length);*/
						break indexOf;
					}
				}
				return result;
			}
			int newLen = _count - token_length + value_length;
			if (newLen > _ca.length) {
				char[] copy = new char[newLen * 2];
				System.arraycopy(_ca, 0, copy, 0, _count);
				_ca = copy;
			}
			int d = 0 - token_length + value_length;
			if (d < 0)
				{ for (int i = end; i <= _count-1; i++) _ca[i+d] = _ca[i]; }
			else if (d > 0)
				{ for (int i = _count-1; i >= end; i--) _ca[i+d] = _ca[i]; }
			_count = newLen;
		//	value.getChars(0, value_length, _ca, start);
			for (int i = 0; i < value_length; i++) //CharSequence value
				_ca[start+i] = value.charAt(i);
			++result;
		}
	}
	public int replace(CharSequence token, int value)
	{
		return replace(token, Integer.toString(value));
	}
	public int replace(CharSequence token, double value)
	{
		return replace(token, Double.toString(value));
	}
	@Override
	public String toString()
	{
		return _ca != null ? new String(_ca, 0, _count) : _html;
	}

	/*
	 	<a action="bypass -h Quest 100_SagaOfTheMaestro 0-1">"I'll do it."</a></body></html>
		           |         |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
		           start.....start                         finish
	 */
	private final void buildBypassCache(L2PcInstance activeChar)
	{
        if (activeChar == null)
            return;

		if (_ca != null) { _html = new String(_ca, 0, _count); _ca = null; }	//XXX:[JOJO]

        activeChar.clearBypass();
		int len = _html.length();
		for(int i=0; i<len; i++)
		{
			int start = _html.indexOf("bypass -h", i);
			int finish = _html.indexOf("\"", start);

			if(start < 0 || finish < 0)
				break;

			start += 10;
			i = start;
			int finish2 = _html.indexOf("$",start);
			if (finish2 < finish && finish2 > 0)
                activeChar.addBypass2(_html.substring(start, finish2).trim());
			else
                activeChar.addBypass(_html.substring(start, finish).trim());
			//System.err.println("["+_html.substring(start, finish)+"]");
		}
	}

	@Override
	protected final void writeImpl()
	{
		CharSequence $html = _html;
		if (_ca != null) { $html = new String(_ca, 0, _count); _ca = null; }	//XXX:[JOJO]

		writeC(0x19);

		writeD(_npcObjId);
		writeS($html);
		writeD(_itemId);
	}

	/* (non-Javadoc)
	 * @see net.sf.l2j.gameserver.serverpackets.ServerBasePacket#getType()
	 */
	@Override
	public String getType()
	{
		return _S__1B_NPCHTMLMESSAGE;
	}

}
