package com.ejie.ab04b.util;

import java.util.HashMap;
import java.util.Map;

import com.ejie.ab04b.constantes.ConstantesNum;

import com.ejie.ab04b.exception.AB04BException;

/**
 * CaracteresRarosUtil
 * 
 * @author GFI
 */
public final class CaracteresRarosUtil {

	/**
	 * Instantiates a new caracteres raros util.
	 */
	private CaracteresRarosUtil() {
	}

	/**
	 * Given a string containing entity escapes, returns a string containing the
	 * actual Unicode characters corresponding to the escapes.
	 *
	 * @param s1
	 *            the s 1
	 * @return the string
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */

	public static String htmlUnescape(String s1) throws AB04BException {
		try {
			return htmlUnescape(s1, false);
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Html unescape.
	 *
	 * @param s1
	 *            the s 1
	 * @param all
	 *            the all
	 * @return the string
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	public static String htmlUnescape(String s1, boolean all)
			throws AB04BException {
		try {
			StringBuffer buf = new StringBuffer();
			int posAct = 0;
			int posPost = s1.indexOf('&', posAct);
			int i = posPost;
			while (posAct < s1.length()) {
				if (i == -1) {
					buf.append(s1.substring(posAct, s1.length()));
					posAct = s1.length();
				} else {
					buf.append(s1.substring(posAct, posPost));
					char ch = s1.charAt(i);
					int semi = s1.indexOf(';', i + 1);
					if (semi == -1) {
						buf.append(ch);
						posAct++;
						continue;
					}
					String entity = s1.substring(i + 1, semi);
					Integer iso;
					if (entity.charAt(0) == '#') {
						iso = Integer.valueOf(entity.substring(1));
					} else {
						if (all) {
							iso = (Integer) allE2i.get(entity);
						} else {
							iso = (Integer) e2i.get(entity);
						}
					}
					if (iso == null) {
						buf.append("&" + entity + ";");
					} else {
						buf.append((char) (iso.intValue()));
					}
					if (semi > 0) {
						posPost = s1.indexOf('&', semi);
						posAct = semi + 1;
					}
				}
				i = s1.indexOf('&', posAct);
			}
			return buf.toString();
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Turns funky characters into HTML entity equivalents
	 * <p>
	 * e.g. <tt>"bread" & "butter"</tt> =>
	 * <tt>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</tt>.
	 * Update: supports nearly all HTML entities, including funky accents. See
	 * the source code for more detail.
	 *
	 * @param s1
	 *            the s 1
	 * @return the string
	 * @throws AB04BException
	 *             the AB 04 B exception
	 * @see #htmlunescape(String)
	 */

	public static String htmlEscape(String s1) throws AB04BException {
		try {
			return htmlEscape(s1, false);
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Html escape.
	 *
	 * @param s1
	 *            the s 1
	 * @param all
	 *            the all
	 * @return the string
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	public static String htmlEscape(String s1, boolean all)
			throws AB04BException {
		try {
			StringBuffer buf = new StringBuffer();
			int i;
			for (i = 0; i < s1.length(); ++i) {
				char ch = s1.charAt(i);
				String entity;
				if (all) {
					entity = (String) allI2e.get(Integer.valueOf((int) ch));
				} else {
					entity = (String) i2e.get(Integer.valueOf((int) ch));
				}
				if (entity == null) {
					/*
					 * if (((int)ch) > 128) { buf.append("&#" + ((int)ch) +
					 * ";"); } else { buf.append(ch); }
					 */

					buf.append(ch);

				} // solo se van a convertir los que sean <175
					// else if (((int)ch) < 175)
				else if (((int) ch) < ConstantesNum.NUM_256) {
					buf.append("&" + entity + ";");
				} else {
					buf.append(ch);
				}

			}
			return buf.toString();
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	// see http://hotwired.lycos.com/webmonkey/reference/special_characters/
	private static Object[][] entities = {
			// {"#39", new Integer(39)}, // ' - apostrophe

			// {"quot", new Integer(34)}, // " - double-quote

			/*
			 * {"amp", new Integer(38)}, // & - ampersand //{"lt", new
			 * Integer(60)}, // < - less-than //{"gt", new Integer(62)}, // > -
			 * greater-than //{"nbsp", new Integer(160)}, // non-breaking space
			 * 
			 * {"copy", new Integer(169)}, // � - copyright {"reg", new
			 * Integer(174)}, // � - registered trademark {"Agrave", new
			 * Integer(192)}, // � - uppercase A, grave accent {"Aacute", new
			 * Integer(193)}, // � - uppercase A, acute accent {"Acirc", new
			 * Integer(194)}, // � - uppercase A, circumflex accent {"Atilde",
			 * new Integer(195)}, // � - uppercase A, tilde {"Auml", new
			 * Integer(196)}, // � - uppercase A, umlaut {"Aring", new
			 * Integer(197)}, // � - uppercase A, ring {"AElig", new
			 * Integer(198)}, // � - uppercase AE {"Ccedil", new Integer(199)},
			 * // � - uppercase C, cedilla {"Egrave", new Integer(200)}, // � -
			 * uppercase E, grave accent {"Eacute", new Integer(201)}, // � -
			 * uppercase E, acute accent {"Ecirc", new Integer(202)}, // � -
			 * uppercase E, circumflex accent {"Euml", new Integer(203)}, // � -
			 * uppercase E, umlaut {"Igrave", new Integer(204)}, // � -
			 * uppercase I, grave accent {"Iacute", new Integer(205)}, // � -
			 * uppercase I, acute accent {"Icirc", new Integer(206)}, // � -
			 * uppercase I, circumflex accent {"Iuml", new Integer(207)}, // � -
			 * uppercase I, umlaut {"ETH", new Integer(208)}, // � - uppercase
			 * Eth, Icelandic {"Ntilde", new Integer(209)}, // � - uppercase N,
			 * tilde {"Ograve", new Integer(210)}, // � - uppercase O, grave
			 * accent {"Oacute", new Integer(211)}, // � - uppercase O, acute
			 * accent {"Ocirc", new Integer(212)}, // � - uppercase O,
			 * circumflex accent {"Otilde", new Integer(213)}, // � - uppercase
			 * O, tilde {"Ouml", new Integer(214)}, // � - uppercase O, umlaut
			 * {"Oslash", new Integer(216)}, // � - uppercase O, slash
			 * {"Ugrave", new Integer(217)}, // � - uppercase U, grave accent
			 * {"Uacute", new Integer(218)}, // � - uppercase U, acute accent
			 * {"Ucirc", new Integer(219)}, // � - uppercase U, circumflex
			 * accent {"Uuml", new Integer(220)}, // � - uppercase U, umlaut
			 * {"Yacute", new Integer(221)}, // � - uppercase Y, acute accent
			 * {"THORN", new Integer(222)}, // � - uppercase THORN, Icelandic
			 * {"szlig", new Integer(223)}, // � - lowercase sharps, German
			 * {"agrave", new Integer(224)}, // � - lowercase a, grave accent
			 * {"aacute", new Integer(225)}, // � - lowercase a, acute accent
			 * {"acirc", new Integer(226)}, // � - lowercase a, circumflex
			 * accent {"atilde", new Integer(227)}, // � - lowercase a, tilde
			 * {"auml", new Integer(228)}, // � - lowercase a, umlaut {"aring",
			 * new Integer(229)}, // � - lowercase a, ring {"aelig", new
			 * Integer(230)}, // � - lowercase ae {"ccedil", new Integer(231)},
			 * // � - lowercase c, cedilla {"egrave", new Integer(232)}, // � -
			 * lowercase e, grave accent {"eacute", new Integer(233)}, // � -
			 * lowercase e, acute accent {"ecirc", new Integer(234)}, // � -
			 * lowercase e, circumflex accent {"euml", new Integer(235)}, // � -
			 * lowercase e, umlaut {"igrave", new Integer(236)}, // � -
			 * lowercase i, grave accent {"iacute", new Integer(237)}, // � -
			 * lowercase i, acute accent {"icirc", new Integer(238)}, // � -
			 * lowercase i, circumflex accent {"iuml", new Integer(239)}, // � -
			 * lowercase i, umlaut {"igrave", new Integer(236)}, // � -
			 * lowercase i, grave accent {"iacute", new Integer(237)}, // � -
			 * lowercase i, acute accent {"icirc", new Integer(238)}, // � -
			 * lowercase i, circumflex accent {"iuml", new Integer(239)}, // � -
			 * lowercase i, umlaut {"eth", new Integer(240)}, // � - lowercase
			 * eth, Icelandic {"ntilde", new Integer(241)}, // � - lowercase n,
			 * tilde {"ograve", new Integer(242)}, // � - lowercase o, grave
			 * accent {"oacute", new Integer(243)}, // � - lowercase o, acute
			 * accent {"ocirc", new Integer(244)}, // � - lowercase o,
			 * circumflex accent {"otilde", new Integer(245)}, // � - lowercase
			 * o, tilde {"ouml", new Integer(246)}, // � - lowercase o, umlaut
			 * {"oslash", new Integer(248)}, // � - lowercase o, slash
			 * {"ugrave", new Integer(249)}, // � - lowercase u, grave accent
			 * {"uacute", new Integer(250)}, // � - lowercase u, acute accent
			 * {"ucirc", new Integer(251)}, // � - lowercase u, circumflex
			 * accent {"uuml", new Integer(252)}, // � - lowercase u, umlaut
			 * {"yacute", new Integer(253)}, // � - lowercase y, acute accent
			 * {"thorn", new Integer(254)}, // � - lowercase thorn, Icelandic
			 * {"yuml", new Integer(255)}, // � - lowercase y, umlaut {"euro",
			 * new Integer(8364)}, // Euro symbol
			 */

			{ "amp", new Integer(ConstantesNum.NUM_38) } // & - ampersand

	};

	private static Object[][] allEntities = {
			{ "#39", new Integer(ConstantesNum.NUM_39) }, // ' -
			// apostrophe
			{ "quot", new Integer(ConstantesNum.NUM_34) }, // " - double-quote
			{ "amp", new Integer(ConstantesNum.NUM_38) }, // & - ampersand
			{ "lt", new Integer(ConstantesNum.NUM_60) }, // < - less-than
			{ "gt", new Integer(ConstantesNum.NUM_62) }, // > - greater-than
			{ "nbsp", new Integer(ConstantesNum.NUM_160) }, // non-breaking
															// space
			{ "copy", new Integer(ConstantesNum.NUM_169) }, // � - copyright
			{ "reg", new Integer(ConstantesNum.NUM_174) }, // � - registered
															// trademark
			{ "Agrave", new Integer(ConstantesNum.NUM_192) }, // � - uppercase
																// A, grave
																// accent
			{ "Aacute", new Integer(ConstantesNum.NUM_193) }, // � - uppercase
																// A, acute
																// accent
			{ "Acirc", new Integer(ConstantesNum.NUM_194) }, // � - uppercase A,
																// circumflex
																// accent
			{ "Atilde", new Integer(ConstantesNum.NUM_195) }, // � - uppercase
																// A, tilde
			{ "Auml", new Integer(ConstantesNum.NUM_196) }, // � - uppercase A,
															// umlaut
			{ "Aring", new Integer(ConstantesNum.NUM_197) }, // � - uppercase A,
																// ring
			{ "AElig", new Integer(ConstantesNum.NUM_198) }, // � - uppercase AE
			{ "Ccedil", new Integer(ConstantesNum.NUM_199) }, // � - uppercase
																// C, cedilla
			{ "Egrave", new Integer(ConstantesNum.NUM_200) }, // � - uppercase
																// E, grave
																// accent
			{ "Eacute", new Integer(ConstantesNum.NUM_201) }, // � - uppercase
																// E, acute
																// accent
			{ "Ecirc", new Integer(ConstantesNum.NUM_202) }, // � - uppercase E,
																// circumflex
																// accent
			{ "Euml", new Integer(ConstantesNum.NUM_203) }, // � - uppercase E,
															// umlaut
			{ "Igrave", new Integer(ConstantesNum.NUM_204) }, // � - uppercase
																// I, grave
																// accent
			{ "Iacute", new Integer(ConstantesNum.NUM_205) }, // � - uppercase
																// I, acute
																// accent
			{ "Icirc", new Integer(ConstantesNum.NUM_206) }, // � - uppercase I,
																// circumflex
																// accent
			{ "Iuml", new Integer(ConstantesNum.NUM_207) }, // � - uppercase I,
															// umlaut
			{ "ETH", new Integer(ConstantesNum.NUM_208) }, // � - uppercase Eth,
															// Icelandic
			{ "Ntilde", new Integer(ConstantesNum.NUM_209) }, // � - uppercase
																// N, tilde
			{ "Ograve", new Integer(ConstantesNum.NUM_210) }, // � - uppercase
																// O, grave
																// accent
			{ "Oacute", new Integer(ConstantesNum.NUM_211) }, // � - uppercase
																// O, acute
																// accent
			{ "Ocirc", new Integer(ConstantesNum.NUM_212) }, // � - uppercase O,
																// circumflex
																// accent
			{ "Otilde", new Integer(ConstantesNum.NUM_213) }, // � - uppercase
																// O, tilde
			{ "Ouml", new Integer(ConstantesNum.NUM_214) }, // � - uppercase O,
															// umlaut
			{ "Oslash", new Integer(ConstantesNum.NUM_216) }, // � - uppercase
																// O, slash
			{ "Ugrave", new Integer(ConstantesNum.NUM_217) }, // � - uppercase
																// U, grave
																// accent
			{ "Uacute", new Integer(ConstantesNum.NUM_218) }, // � - uppercase
																// U, acute
																// accent
			{ "Ucirc", new Integer(ConstantesNum.NUM_219) }, // � - uppercase U,
																// circumflex
																// accent
			{ "Uuml", new Integer(ConstantesNum.NUM_220) }, // � - uppercase U,
															// umlaut
			{ "Yacute", new Integer(ConstantesNum.NUM_221) }, // � - uppercase
																// Y, acute
																// accent
			{ "THORN", new Integer(ConstantesNum.NUM_222) }, // � - uppercase
																// THORN,
																// Icelandic
			{ "szlig", new Integer(ConstantesNum.NUM_223) }, // � - lowercase
																// sharps,
																// German
			{ "agrave", new Integer(ConstantesNum.NUM_224) }, // � - lowercase
																// a, grave
																// accent
			{ "aacute", new Integer(ConstantesNum.NUM_225) }, // � - lowercase
																// a, acute
																// accent
			{ "acirc", new Integer(ConstantesNum.NUM_226) }, // � - lowercase a,
																// circumflex
																// accent
			{ "atilde", new Integer(ConstantesNum.NUM_227) }, // � - lowercase
																// a, tilde
			{ "auml", new Integer(ConstantesNum.NUM_228) }, // � - lowercase a,
															// umlaut
			{ "aring", new Integer(ConstantesNum.NUM_229) }, // � - lowercase a,
																// ring
			{ "aelig", new Integer(ConstantesNum.NUM_230) }, // � - lowercase ae
			{ "ccedil", new Integer(ConstantesNum.NUM_231) }, // � - lowercase
																// c, cedilla
			{ "egrave", new Integer(ConstantesNum.NUM_232) }, // � - lowercase
																// e, grave
																// accent
			{ "eacute", new Integer(ConstantesNum.NUM_233) }, // � - lowercase
																// e, acute
																// accent
			{ "ecirc", new Integer(ConstantesNum.NUM_234) }, // � - lowercase e,
																// circumflex
																// accent
			{ "euml", new Integer(ConstantesNum.NUM_235) }, // � - lowercase e,
															// umlaut
			{ "igrave", new Integer(ConstantesNum.NUM_236) }, // � - lowercase
																// i, grave
																// accent
			{ "iacute", new Integer(ConstantesNum.NUM_237) }, // � - lowercase
																// i, acute
																// accent
			{ "icirc", new Integer(ConstantesNum.NUM_238) }, // � - lowercase i,
																// circumflex
																// accent
			{ "iuml", new Integer(ConstantesNum.NUM_239) }, // � - lowercase i,
															// umlaut
			{ "igrave", new Integer(ConstantesNum.NUM_236) }, // � - lowercase
																// i, grave
																// accent
			{ "iacute", new Integer(ConstantesNum.NUM_237) }, // � - lowercase
																// i, acute
																// accent
			{ "icirc", new Integer(ConstantesNum.NUM_238) }, // � - lowercase i,
																// circumflex
																// accent
			{ "iuml", new Integer(ConstantesNum.NUM_239) }, // � - lowercase i,
															// umlaut
			{ "eth", new Integer(ConstantesNum.NUM_240) }, // � - lowercase eth,
															// Icelandic
			{ "ntilde", new Integer(ConstantesNum.NUM_241) }, // � - lowercase
																// n, tilde
			{ "ograve", new Integer(ConstantesNum.NUM_242) }, // � - lowercase
																// o, grave
																// accent
			{ "oacute", new Integer(ConstantesNum.NUM_243) }, // � - lowercase
																// o, acute
																// accent
			{ "ocirc", new Integer(ConstantesNum.NUM_244) }, // � - lowercase o,
																// circumflex
																// accent
			{ "otilde", new Integer(ConstantesNum.NUM_245) }, // � - lowercase
																// o, tilde
			{ "ouml", new Integer(ConstantesNum.NUM_246) }, // � - lowercase o,
															// umlaut
			{ "oslash", new Integer(ConstantesNum.NUM_248) }, // � - lowercase
																// o, slash
			{ "ugrave", new Integer(ConstantesNum.NUM_249) }, // � - lowercase
																// u, grave
																// accent
			{ "uacute", new Integer(ConstantesNum.NUM_250) }, // � - lowercase
																// u, acute
																// accent
			{ "ucirc", new Integer(ConstantesNum.NUM_251) }, // � - lowercase u,
																// circumflex
																// accent
			{ "uuml", new Integer(ConstantesNum.NUM_252) }, // � - lowercase u,
															// umlaut
			{ "yacute", new Integer(ConstantesNum.NUM_253) }, // � - lowercase
																// y, acute
																// accent
			{ "thorn", new Integer(ConstantesNum.NUM_254) }, // � - lowercase
																// thorn,
																// Icelandic
			{ "yuml", new Integer(ConstantesNum.NUM_255) }, // � - lowercase y,
															// umlaut
			{ "euro", new Integer(ConstantesNum.NUM_8364) }, // Euro symbol
	};
	private static Map e2i = new HashMap();
	private static Map i2e = new HashMap();
	private static Map allE2i = new HashMap();
	private static Map allI2e = new HashMap();

	static {
		for (int i = 0; i < entities.length; ++i) {
			e2i.put(entities[i][0], entities[i][1]);
			i2e.put(entities[i][1], entities[i][0]);
		}
	}
	static {
		for (int i = 0; i < allEntities.length; ++i) {
			allE2i.put(allEntities[i][0], allEntities[i][1]);
			allI2e.put(allEntities[i][1], allEntities[i][0]);
		}
	}

	/**
	 * Xml to cdata.
	 *
	 * @param str
	 *            the str
	 * @return the string
	 */
	public static String xmlToCdata(String str) {
		final String iniCdata = "<![CDATA[";
		final String finCdata = "]]>";
		StringBuffer buf = new StringBuffer();

		buf.append(iniCdata);
		buf.append(str);
		buf.append(finCdata);

		return buf.toString();
	}
}
