/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework 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 any later version.
 *
 * Nuts Framework 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 Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.core.lang;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

/**
 * utility class for string escape
 */
public class StringEscapeUtils extends org.apache.commons.lang3.StringEscapeUtils {

	/**
	 * escapeSqlLike
	 * @param str string
	 * @return escaped string
	 */
	public static String escapeSqlLike(String str) {
		final char esc = '~';

		StringBuilder result = new StringBuilder();

		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (c == esc) {
				result.append(esc);
				result.append(esc);
				continue;
			}
			if (c == '%' || c == '_') {
				result.append(esc);
				result.append(c);
			}
			else {
				result.append(c);
			}
		}

		return result.toString();
	}

	/**
	 * <p>
	 * Escapes the characters in a <code>String</code> to be suitable to pass to
	 * an SQL query.
	 * </p>
	 * 
	 * <p>
	 * For example,
	 * 
	 * <pre>
	 * statement.executeQuery(&quot;SELECT * FROM MOVIES WHERE TITLE='&quot;
	 * 		+ StringEscapeUtils.escapeSql(&quot;McHale's Navy&quot;) + &quot;'&quot;);
	 * </pre>
	 * 
	 * </p>
	 * 
	 * <p>
	 * At present, this method only turns single-quotes into doubled
	 * single-quotes (<code>"McHale's Navy"</code> =>
	 * <code>"McHale''s Navy"</code>). It does not handle the cases of percent
	 * (%) or underscore (_) for use in LIKE clauses.
	 * </p>
	 * 
	 * see http://www.jguru.com/faq/view.jsp?EID=8881
	 * 
	 * @param str
	 *            the string to escape, may be null
	 * @return a new String, escaped for SQL, <code>null</code> if null string
	 *         input
	 */
	public static String escapeSql(String str) {
		return StringUtils.replace(str, "'", "''");
	}

	/**
	 * escapeJavaScript
	 * @param str string
	 * @return escaped string
	 */
	public static String escapeJavaScript(String str) {
		return escapeEcmaScript(str);
	}
	
	public static class EscapePhtmlWriter extends Writer {

		private Writer writer;
		
		public EscapePhtmlWriter(Writer writer) {
			super();
			this.writer = writer;
		}

		@Override
		public void close() throws IOException {
			writer.close();
		}

		@Override
		public void flush() throws IOException {
			writer.flush();
		}

		@Override
		public void write(char[] cbuf, int off, int len) throws IOException {
			for (int i = 0; i < len; i++, off++) {
				char ch = cbuf[off];
				switch (ch) {
				case '\t':
					writer.write("&nbsp;&nbsp;");
					break;
				case '\n':
					writer.write("<br/>");
					break;
				case '\r':
					break;
				case ' ':
					writer.write("&nbsp;");
					break;
				default:
					writer.write(ch);
					break;
				}
			}
		}
	}
	
	public static String escapeHtml(String input) {
		return escapeHtml4(input);
	}

	public static void escapeHtml(String input, Writer writer) throws IOException {
		ESCAPE_HTML4.translate(input, writer);
	}

    /**
     * <p>Escapes the characters in a <code>String</code> using HTML entities.</p>
     *
     * <p>
     * For example:
     * </p> 
     * <p><code>"bread" & "butter"</code></p>
     * becomes:
     * <p>
     * <code>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</code>.
     * </p>
     *
     * <p>Supports all known HTML 4.0 entities, including funky accents.
     * Note that the commonly used apostrophe escape character (&amp;apos;)
     * is not a legal entity and so is not supported). </p>
     *
     * @param str  the <code>String</code> to escape, may be null
     * @return a new escaped <code>String</code>, <code>null</code> if null string input
     */
	public static String escapePhtml(String str) {
		if (str == null) {
			return null;
		}

		try {
			StringWriter sw = new StringWriter((int)(str.length() * 1.5));
			escapeHtml(str, new EscapePhtmlWriter(sw));
			return sw.toString();
		}
		catch (IOException ioe) {
			// should be impossible
			throw new RuntimeException(ioe);
		}
	}
}
