//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.utils;

import java.net.URI;
import java.util.List;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.epf.common.CommonPlugin;

import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.util.StringTokenizer;

/**
 * A helper class for manuipulating strings.
 * 
 * @author Kelvin Low
 * @author Jinhua Xi
 * @since 1.0
 */
public class StrUtil {

	public static final String TAB = "\t"; //$NON-NLS-1$

	private static final String REGEXP_ANY_SPECIAL_CHARS = "(`|~|!|@|#|\\$|%|\\^|&|\\*|\\(|\\)|\\+|=|\\[|\\]|\\||\\:|\"|<|>|\\?|/|'|\\s|\\\\)+"; //$NON-NLS-1$

	private static final String REGEXP_INVALID_PUBLISHED_PATH_CHARS = "(\\[|#|\\*|\\?|\"|<|>|\\||!|%|/|\\])+"; //$NON-NLS-1$

	private static final String REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX = "(\\[|#|\\*|\\?|\"|<|>|\\||!|%|\\])+"; //$NON-NLS-1$

	private static final String REGEXP_INVALID_FILENAME_CHARS = "(\\[|#|/|\\\\|\\:|\\*|\\?|\"|<|>|\\||\\]|\\s)+"; //$NON-NLS-1$

	private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	public static final String LINE_FEED = System.getProperty("line.separator"); //$NON-NLS-1$

	public static final String ESCAPED_LF = "&#xA;"; //$NON-NLS-1$

	public static final String ESCAPED_CR = "&#xD;"; //$NON-NLS-1$

	public static final String ESCAPED_LINE_FEED = LINE_FEED.replace(
			"\n", ESCAPED_LF).replace("\r", ESCAPED_CR); //$NON-NLS-1$ //$NON-NLS-2$

	public static final String LINE_FEED_REGEX = LINE_FEED.replaceAll(
			"\\\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$

	public static final String ESCAPED_LINE_FEED_REGEX = ESCAPED_LINE_FEED;

	public static final String HTML_BREAK = "<br/>";//$NON-NLS-1$

	public static final String HTML_COPY = "&copy;";//$NON-NLS-1$

	public static final String HTML_EURO = "&euro;";//$NON-NLS-1$ 	

	public static final String HTML_REG = "&reg;";//$NON-NLS-1$ 

	public static final String HTML_TRADEMARK = "&trade;";//$NON-NLS-1$

	/**
	 * Private constructor to prevent this class from being instantiated. All
	 * methods in this class should be static.
	 */
	private StrUtil() {
	}

	/**
	 * Tests for null string.
	 * <p>
	 * A null string is defined as one that has an empty reference or has zero
	 * length.
	 * 
	 * @param str
	 *            a string
	 * @return <code>true</code> if the given string is a null string
	 */
	public static boolean isNull(String str) {
		return str == null || str.length() == 0;
	}

	/**
	 * Tests for blank string.
	 * <p>
	 * A blank string is defined as one that has an empty reference or has zero
	 * length after the leading and trailing space characters are trimmed.
	 * 
	 * @param str
	 *            a string
	 * @return <code>true</code> if the given string is a blank string
	 */
	public static boolean isBlank(String str) {
		return str == null || str.trim().length() == 0;
	}

	/**
	 * Removes the leading and trailing space characters from a string.
	 * 
	 * @param str
	 *            a string
	 * @return a string with no leading and trailing space characters
	 */
	public static String trim(String str) {
		return str == null ? null : str.trim();
	}

	/**
	 * Removes whitespace characters (TAB, CR, LF and SPACE) from a string.
	 * 
	 * @param str
	 *            a string
	 * @return a string with whitespace characters removed
	 */
	public static String removeWhiteSpaceChars(String str) {
		int len = (str == null) ? 0 : str.length();
		for (int i = 0; i < len; i++) {
			switch (str.charAt(i)) {
			case '\t':
			case '\r':
			case '\n':
			case ' ':
				break;
			default:
				return str;
			}
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Splits a string into an array of string tokens.
	 * 
	 * @param str
	 *            a string
	 * @param sep
	 *            a string containing the string separators
	 * @param count
	 *            the desired number of string tokens
	 * @return an array of string tokens
	 */
	public static String[] split(String str, String sep, int count) {
		if (str == null || count == 0 || count < -1) {
			return null;
		}

		StringTokenizer tokenizer = new StringTokenizer(str, sep,
				count == -1 ? false : true);

		if (count == -1) {
			count = tokenizer.countTokens();
		}

		String[] result = new String[count];
		int i = 0;
		while (tokenizer.hasMoreTokens()) {
			String t = tokenizer.nextToken();
			if (i < count) {
				if ((t.length() == 1) && (sep.indexOf(t) != -1)) {
					continue;
				}
				result[i++] = t;
			} else {
				result[count - 1] += t;
			}
		}
		return result;
	}

	/**
	 * Splits a string into an array of string tokens.
	 * 
	 * @param str
	 *            a string
	 * @param sep
	 *            a string containing the string separators
	 * @return an array of string tokens
	 */
	public static String[] split(String str, String sep) {
		return split(str, sep, -1);
	}

	/**
	 * Replaces a substring within a string with another substring.
	 * <p>
	 * Note: Only the first occurrence of the substring will be replaced.
	 * 
	 * @param str
	 *            a string
	 * @param src
	 *            the substring to replace
	 * @param tgt
	 *            the substring to use for the replacement
	 * @return a string with the first substring replaced
	 * 
	 * TODO: Review implementation. Call String.replaceFirst() instead?
	 */
	public static String replace(String str, String src, String tgt) {
		if ((str == null || str.length() == 0)
				|| (src == null || src.length() == 0)) {
			return str;
		}

		String tmpStr = str;
		int index;
		while ((index = tmpStr.indexOf(src)) != -1) {
			tmpStr = tmpStr.substring(0, index) + tgt
					+ tmpStr.substring(index + src.length());
		}
		return tmpStr;
	}

	/**
	 * Returns the integer value of a string.
	 * 
	 * @param str
	 *            a string
	 * @param defaultValue
	 *            a default integer value for the string
	 * @return the integer value of the given string
	 */
	public static int getIntValue(String str, int defaultValue) {
		if (StrUtil.isBlank(str)) {
			return defaultValue;
		}

		try {
			return Integer.parseInt(str);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}

	/**
	 * Returns an array of bytes representing the UTF-8 encoding of a string.
	 * 
	 * @param str
	 *            a string
	 * @return a byte array containing the UTF-8 encoding of the given string
	 */
	public static byte[] getUTF8Bytes(String str) {
		char[] c = str.toCharArray();
		int len = c.length;
		int count = 0;
		for (int i = 0; i < len; i++) {
			int ch = c[i];
			if (ch <= 0x7f) {
				count++;
			} else if (ch <= 0x7ff) {
				count += 2;
			} else {
				count += 3;
			}
		}

		byte[] b = new byte[count];
		int off = 0;
		for (int i = 0; i < len; i++) {
			int ch = c[i];
			if (ch <= 0x7f) {
				b[off++] = (byte) ch;
			} else if (ch <= 0x7ff) {
				b[off++] = (byte) ((ch >> 6) | 0xc0);
				b[off++] = (byte) ((ch & 0x3f) | 0x80);
			} else {
				b[off++] = (byte) ((ch >> 12) | 0xe0);
				b[off++] = (byte) (((ch >> 6) & 0x3f) | 0x80);
				b[off++] = (byte) ((ch & 0x3f) | 0x80);
			}
		}
		return b;
	}

	/**
	 * Returns the hexidecimal character representation for an integer.
	 * 
	 * @param value
	 *            an integer
	 * @return the hexidecimal representation
	 */
	private static char toHex(int value) {
		return HEX_DIGITS[(value & 0xF)];
	}

	/**
	 * Returns the escaped Unicode representation of a string.
	 * 
	 * @param str
	 *            a string
	 * @param skipASCII
	 *            if <code>true</code>, avoid escaping the ASCII characters
	 * @return the escaped Unicode representation of the given string
	 */
	public static String toEscapedUnicode(String str, boolean skipASCII) {
		int len = str.length();
		StringBuffer result = new StringBuffer(len * 2);

		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);

			if (skipASCII && ch < 0x007E) {
				result.append(ch);
			} else {
				result.append("\\u"); //$NON-NLS-1$
				result.append(toHex((ch >> 12) & 0xF));
				result.append(toHex((ch >> 8) & 0xF));
				result.append(toHex((ch >> 4) & 0xF));
				result.append(toHex(ch & 0xF));
			}
		}

		return result.toString();
	}

	/**
	 * Returns the escaped HTML representation of a string.
	 * 
	 * @param html
	 *            a HTML string
	 * @return the escaped Unicode representation of the given HTML string
	 */
	public static String getEscapedHTML(String html) {
		if (html == null || html.length() == 0) {
			return ""; //$NON-NLS-1$
		}

		StringBuffer result = new StringBuffer();
		int length = html.length();
		for (int i = 0; i < length; i++) {
			char ch = html.charAt(i);
			switch (ch) {
			case '%':
				if (i + 4 < length) {
					String hexStr = html.substring(i + 1, i + 5);
					boolean validHextStr = true;
					for (int j = 0; j < hexStr.length(); j++) {
						char c = hexStr.charAt(j);
						if (!(c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
							validHextStr = false;
							break;
						}
					}
					if (validHextStr) {
						try {
							int codePoint = Integer.parseInt(hexStr, 16);
							char[] c = UCharacter.toChars(codePoint);
							result.append(c);
							i += 4;
							break;
						} catch (Exception e) {
						}
					}
				}
				result.append(ch);
				break;
			case '\u00a9':
				result.append(HTML_COPY);
				break;
			case '\u00ae':
				result.append(HTML_REG);
				break;
			case '\u20ac':
				result.append(HTML_EURO);
				break;
			case '\u2122':
				result.append(HTML_TRADEMARK);
				break;
			default:
				result.append(ch);
				break;
			}
		}
		return result.toString();
	}

	/**
	 * Returns the plain text from HTML text.
	 * <p>
	 * Note: All HTML tags will be stripped.
	 * 
	 * @param html
	 *            the HTML text.
	 * @return the plain text representation of the given HTML text
	 */
	public static String getPlainText(String html) {
		if (html == null) {
			return ""; //$NON-NLS-1$
		}

		final Pattern p_plaintext_filter = Pattern.compile(
				"<[^>]*?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
		final Pattern p_plaintext_filter2 = Pattern.compile(
				"&.{1,5}[^;];", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
		final Pattern p_plaintext_filter3 = Pattern.compile(
				"\\s+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

		String result = html.replaceAll(p_plaintext_filter.pattern(), " ") //$NON-NLS-1$
				.replaceAll(p_plaintext_filter2.pattern(), " ") //$NON-NLS-1$
				.replaceAll(p_plaintext_filter3.pattern(), " "); //$NON-NLS-1$
		return result;
	}

	/**
	 * Converts a string into a valid file name.
	 * 
	 * @param str
	 *            a string
	 * @return a valid file name derived from the given string
	 */
	public static String makeValidFileName(String str) {
		if (str == null) {
			return ""; //$NON-NLS-1$
		}
		return getPlainText(str)
				.replaceAll(REGEXP_INVALID_FILENAME_CHARS, " ").trim(); //$NON-NLS-1$ 
	}

	public static String removeSpecialCharacters(String str) {
		if (str == null) {
			return ""; //$NON-NLS-1$
		}
		return getPlainText(str)
				.replaceAll(REGEXP_ANY_SPECIAL_CHARS, " ").trim(); //$NON-NLS-1$ 
	}

	/**
	 * Returns true if the path does not contain any invalid filename
	 * characters.
	 * 
	 * @param path
	 *            the file path
	 * @return <code>true</code> if the given path contains only valid
	 *         filename characters
	 */
	public static boolean isValidPublishPath(String path) {
		// return path.replaceAll(invalidPublishPathCharsRegExp,
		// "").equals(path);

		if (Platform.getOS().equals(Platform.WS_WIN32)) {
			return path
					.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS, "").equals(path); //$NON-NLS-1$
		}

		// else default to Linux
		return path
				.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX, "").equals(path); //$NON-NLS-1$
	}

	/**
	 * Returns the lower-case of str unless the current locale is German
	 * 
	 * @param str
	 * @return
	 */
	public static String toLower(String str) {
		if (Platform.getNL().startsWith("de")) { //$NON-NLS-1$
			return str;
		}
		return str.toLowerCase();
	}

	/**
	 * escape the " and '
	 * 
	 * @param str
	 * @return
	 */
	public static String escape(String str) {
		return str.replaceAll("'", "\\\\\'").replaceAll("\"", "\\\\\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
	}

	/**
	 * Converts a <code>List</code> to an String array.
	 * 
	 * @param list
	 *            a <code>List</code>
	 * @return a String array
	 */
	public static String[] convertListToStrArray(List list) {
		if (list != null) {
			int cnt = list.size();
			String[] strArray = new String[cnt];

			for (int i = 0; i < cnt; i++) {
				String str = (String) list.get(i);
				strArray[i] = new String(str);
			}
			return strArray;
		} else {
			return null;
		}
	}

	public static boolean isValidName(String name) {
		return name.replaceAll(REGEXP_ANY_SPECIAL_CHARS, "").equals(name); //$NON-NLS-1$		
	}

	/**
	 * added some test code
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		String text = "A&%      `&#           $~!@#$%^&*()_-+={}[\"]:|\\:;\"'<,>.?/ \t\r\nZ"; //$NON-NLS-1$

		System.out.println("[" + text + "] <== text"); //$NON-NLS-1$ //$NON-NLS-2$
		System.out.println("[" + text.replaceAll(REGEXP_ANY_SPECIAL_CHARS, " ") //$NON-NLS-1$ //$NON-NLS-2$
				+ "] <== All"); //$NON-NLS-1$
		System.out.println("[" //$NON-NLS-1$
				+ text.replaceAll(REGEXP_INVALID_FILENAME_CHARS, " ") //$NON-NLS-1$
				+ "] <== File Name"); //$NON-NLS-1$
		System.out.println("[" //$NON-NLS-1$
				+ text.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS, " ") //$NON-NLS-1$
				+ "] <== path"); //$NON-NLS-1$
		System.out.println("[" //$NON-NLS-1$
				+ text.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX,
						" ") + "] <== path, Linux"); //$NON-NLS-1$ //$NON-NLS-2$

		System.out.println(""); //$NON-NLS-1$
	}

	/**
	 * Converts the platform line-separator (\n or \n\r or \r) to &lt;br/&gt;
	 * 
	 * @param text
	 * @return
	 */
	public static String convertNewlinesToHTML(String text) {
		if (text != null) {
			text = text.replaceAll(LINE_FEED_REGEX, HTML_BREAK + LINE_FEED);
			text = text.replaceAll(ESCAPED_LINE_FEED_REGEX, HTML_BREAK
					+ ESCAPED_LINE_FEED);
		}
		return text;
	}

	public static URI toURI(String pathStr) {
		if (pathStr != null && pathStr.length() > 0) {
			IPath path = Path.fromOSString(pathStr);
			try {
				return path.toFile().toURI();
			} catch (Exception e) {
				CommonPlugin.getDefault().getLogger().logError(e);
			}
		}
		return null;
	}

}