package gov.va.med.fw.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This helper class is intended to be used by tags and decryption filter to
 * encrypt and decrypt the information.
 * 
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class StringUtils extends org.apache.commons.lang.StringUtils {
	private static final char AMPERSAND = '&';

	private static final char SEMICOLON = ';';

	private static final Map replacementMap = new HashMap();

	static {
		replacementMap.put("amp", "&");
		replacementMap.put("gt", ">");
		replacementMap.put("lt", "<");
		replacementMap.put("quot", "\"");
		replacementMap.put("#39", "\\");
	}

/**
     * Replaces the following string. "&amp;"  -> '&' "&gt;"   -> '>' "&lt;"   -> '<' "&quot;" -> '"' "&#39;"  -> '\'
     *
     * @param pString the string to work on
     *
     * @return string after all the entities replaced
     */
	public static String replaceHtmlEntities(String pString) {
		StringBuilder sb = new StringBuilder();
		int base = 0;
		int index = base;
		while ((index = pString.indexOf(AMPERSAND, base)) >= base) {
			sb.append(pString.substring(base, index));
			int index2 = pString.indexOf(SEMICOLON, index);
			if (index2 != -1 && (index2 - index < 8)) {
				String token = pString.substring(index + 1, index2);
				String replacement = (String) replacementMap.get(token);
				if (replacement != null) {
					sb.append(replacement);
				} else {
					sb.append(AMPERSAND);
					sb.append(token);
					sb.append(SEMICOLON);
				}
				base = index2 + 1;
			} else {
				sb.append(AMPERSAND);
				base = index + 1;
			}
		}
		sb.append(pString.substring(base));
		return sb.toString();
	}

	public static boolean contains(String[] strings, String string) {
		if (strings == null)
			return false;
		for (int i = 0; i < strings.length; i++) {
			if (StringUtils.equals(strings[i], string))
				return true;
		}
		return false;
	}

	/**
	 * Return true if the given string starts with any of the strings in the
	 * given array.
	 * 
	 * @param string
	 *            - string to compare
	 * @param strings
	 *            - array of strings to comare start with.
	 * 
	 * @return True if the given string starts with the specified strings or
	 *         false if not.
	 */
	public static boolean startsWith(String string, String[] strings) {
		if (string == null || strings == null)
			return false;
		for (int i = 0; i < strings.length; i++) {
			if (string.startsWith(strings[i]))
				return true;
		}
		return false;
	}

	/**
	 * Utility method: Generate string representation of a Collection
	 */
	public static String stringFor(Collection pList, String pListName) {
		final StringBuilder sb = new StringBuilder();
		if (pListName != null) {
			sb.append(pListName);
			sb.append("=");
		}

		if (pList != null) {
			sb.append("{");
			final Iterator iter = pList.iterator();
			while (iter.hasNext()) {
				Object value = iter.next();

				if (value instanceof Map) {
					sb.append(stringFor((Map) value, "map"));
				} else if (value instanceof Collection) {
					sb.append(stringFor((Collection) value, "coll"));
				} else {
					sb.append(value);
				}

				if (iter.hasNext()) {
					sb.append(",");
				}
			}
			sb.append("}");
		} else {
			sb.append("null");
		}
		return sb.toString();
	}

	/**
	 * Utility method: Generate string representation of a Map
	 */
	public static String stringFor(Map pMap, String pMapName) {
		final StringBuilder sb = new StringBuilder();
		if (pMapName != null) {
			sb.append(pMapName);
			sb.append("=");
		}

		if (pMap != null) {
			sb.append("{");

			Set mapSet = pMap.entrySet();
			Iterator iter = mapSet.iterator();
			while (iter.hasNext()) {
				Map.Entry entry = (Map.Entry) iter.next();
				sb.append("(");
				sb.append(entry.getKey());
				sb.append("=");
				Object value = entry.getValue();
				if (value instanceof Map) {
					sb.append(stringFor((Map) value, "map"));
				} else if (value instanceof Collection) {
					sb.append(stringFor((Collection) value, "coll"));
				} else {
					sb.append(value);
				}
				sb.append(")");

				if (iter.hasNext()) {
					sb.append(",");
				}
			}

			sb.append("}");
		} else {
			sb.append("null");
		}
		return sb.toString();

	}

	public static String keepAlphaAndHyphen(String string) {
		StringBuilder cleanString = new StringBuilder();
		if (StringUtils.isNotEmpty(string)) {
			for (int i = 0; i < string.length(); i++) {
				if (Character.isLetter(string.charAt(i)) || string.charAt(i) == '-') {
					cleanString.append(string.charAt(i));
				}
			}
		}
		return cleanString.toString();
	}

	/**
	 * Compares the first string to the second string. The null string will be
	 * treated as the empty string.
	 * 
	 * @param string1
	 *            The first string to compare
	 * @param string2
	 *            The second string to compare
	 * 
	 * @return the comparrison result.
	 */
	public static int compareTo(String string1, String string2) {
		if (string1 == null) {
			string1 = "";
		}
		if (string2 == null) {
			string2 = "";
		}
		return string1.compareTo(string2);
	}

	/**
	 * Returns true if all the chars in a given string are same, false
	 * otherwise. If input string is null, return false. If input string is
	 * empty (0 length), return true.
	 * 
	 * @param string
	 *            - input string to validate
	 * 
	 * @return true|false
	 */
	public static boolean isSameCharString(String string) {
		if (string != null) {
			for (int i = 1; i < string.length(); i++) {
				if (string.charAt(i - 1) != string.charAt(i)) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	/**
	 * Returns the number of times a character is present in a string.
	 * 
	 * @param stringToCompare
	 *            The string.
	 * @param matchString
	 *            The string to search for.
	 * 
	 * @return The number of time the string is present. 0 is returned for null
	 *         or the emptry string.
	 */
	public static int numTimesStringPresent(String stringToCompare, String matchString) {
		// Handle the empty string by returning 0.
		if ((StringUtils.isEmpty(stringToCompare)) || (StringUtils.isEmpty(matchString))) {
			return 0;
		}

		// Initialize our counter and the compare buffer
		int count = 0;
		StringBuilder compareBuffer = new StringBuilder(stringToCompare);

		// Keep looping until the compare buffer is empty
		while (compareBuffer.length() > 0) {
			// Search for the match string in the buffer
			int index = compareBuffer.indexOf(matchString);
			if (index == -1) {
				// We didn't find a match so empty out the string to exit our
				// loop
				compareBuffer.setLength(0);
			} else {
				// We found a match so increment our counter and remove
				// everything up to and including the match
				// from the compare buffer.
				count++;
				compareBuffer.delete(index, index + matchString.length());
			}
		}

		// Return the count
		return count;
	}

	/**
	 * Splits the string into a list of tokens that are separated by the
	 * delimiter.
	 * 
	 * @param string
	 *            the string to split
	 * @param delimiter
	 *            the delimiter to split on
	 * 
	 * @return list of trimmed strings
	 */
	public static List delimitedStringToList(String string, String delimiter) {
		List returnList = new ArrayList();

		if (isNotEmpty(string)) {
			String tokens[] = string.split(delimiter);
			if (tokens != null) {
				for (int i = 0; i < tokens.length; i++) {
					String token = tokens[i].trim();
					if (StringUtils.isNotEmpty(token)) {
						returnList.add(token);
					}
				}
			}
		}

		return returnList;
	}

	/**
	 * Creates a delimited String from the list of entries.
	 * 
	 * @param list
	 *            the list of entries.
	 * @param deliimiter
	 *            the delimited string.
	 * @return the delimited string.
	 */
	public static String listToDelimitedString(List list, String deliimiter) {
		StringBuilder buffer = new StringBuilder();
		if (list != null) {
			for (Iterator iterator = list.iterator(); iterator.hasNext();) {
				Object object = iterator.next();
				if (object != null) {
					if (buffer.length() > 0) {
						buffer.append(deliimiter);
					}
					buffer.append(object.toString());
				}
			}
		}
		return buffer.toString();
	}
}
