/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.utils;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * Utility class of string functions.
 *
 * @author James Moger
 *
 */
public class StringUtils {

	public static final String MD5_TYPE = "MD5:";

	public static final String COMBINED_MD5_TYPE = "CMD5:";

	/**
	 * Returns true if the string is null or empty.
	 *
	 * @param value
	 * @return true if string is null or empty
	 */
	public static boolean isEmpty(String value) {
		return value == null || value.trim().length() == 0;
	}

	/**
	 * Replaces carriage returns and line feeds with html line breaks.
	 *
	 * @param string
	 * @return plain text with html line breaks
	 */
	public static String breakLinesForHtml(String string) {
		return string.replace("\r\n", "<br/>").replace("\r", "<br/>").replace("\n", "<br/>");
	}

	/**
	 * Prepare text for html presentation. Replace sensitive characters with
	 * html entities.
	 *
	 * @param inStr
	 * @param changeSpace
	 * @return plain text escaped for html
	 */
	public static String escapeForHtml(String inStr, boolean changeSpace) {
		StringBuilder retStr = new StringBuilder();
		int i = 0;
		while (i < inStr.length()) {
			if (inStr.charAt(i) == '&') {
				retStr.append("&amp;");
			} else if (inStr.charAt(i) == '<') {
				retStr.append("&lt;");
			} else if (inStr.charAt(i) == '>') {
				retStr.append("&gt;");
			} else if (inStr.charAt(i) == '\"') {
				retStr.append("&quot;");
			} else if (changeSpace && inStr.charAt(i) == ' ') {
				retStr.append("&nbsp;");
			} else if (changeSpace && inStr.charAt(i) == '\t') {
				retStr.append(" &nbsp; &nbsp;");
			} else {
				retStr.append(inStr.charAt(i));
			}
			i++;
		}
		return retStr.toString();
	}

	/**
	 * Decode html entities back into plain text characters.
	 *
	 * @param inStr
	 * @return returns plain text from html
	 */
	public static String decodeFromHtml(String inStr) {
		return inStr.replace("&amp;", "&").replace("&lt;", "<").replace("&gt;", ">")
				.replace("&quot;", "\"").replace("&nbsp;", " ");
	}

	/**
	 * Encodes a url parameter by escaping troublesome characters.
	 *
	 * @param inStr
	 * @return properly escaped url
	 */
	public static String encodeURL(String inStr) {
		StringBuilder retStr = new StringBuilder();
		int i = 0;
		while (i < inStr.length()) {
			if (inStr.charAt(i) == '/') {
				retStr.append("%2F");
			} else if (inStr.charAt(i) == ' ') {
				retStr.append("%20");
			} else if (inStr.charAt(i) == '&') {
				retStr.append("%26");
			} else if (inStr.charAt(i) == '+') {
				retStr.append("%2B");
			} else {
				retStr.append(inStr.charAt(i));
			}
			i++;
		}
		return retStr.toString();
	}

	/**
	 * Flatten the list of strings into a single string with the specified
	 * separator.
	 *
	 * @param values
	 * @param separator
	 * @return flattened list
	 */
	public static String flattenStrings(String[]  values, String separator) {
		return flattenStrings(Arrays.asList(values), separator);
	}

	/**
	 * Flatten the list of strings into a single string with a space separator.
	 *
	 * @param values
	 * @return flattened list
	 */
	public static String flattenStrings(Collection<String> values) {
		return flattenStrings(values, " ");
	}

	/**
	 * Flatten the list of strings into a single string with the specified
	 * separator.
	 *
	 * @param values
	 * @param separator
	 * @return flattened list
	 */
	public static String flattenStrings(Collection<String> values, String separator) {
		StringBuilder sb = new StringBuilder();
		for (String value : values) {
			sb.append(value).append(separator);
		}
		if (sb.length() > 0) {
			// truncate trailing separator
			sb.setLength(sb.length() - separator.length());
		}
		return sb.toString().trim();
	}

	/**
	 * Returns a string trimmed to a maximum length with trailing ellipses. If
	 * the string length is shorter than the max, the original string is
	 * returned.
	 *
	 * @param value
	 * @param max
	 * @return trimmed string
	 */
	public static String trimString(String value, int max) {
		if (value.length() <= max) {
			return value;
		}
		return value.substring(0, max - 3) + "...";
	}

	/**
	 * Left pad a string with the specified character, if the string length is
	 * less than the specified length.
	 *
	 * @param input
	 * @param length
	 * @param pad
	 * @return left-padded string
	 */
	public static String leftPad(String input, int length, char pad) {
		if (input.length() < length) {
			StringBuilder sb = new StringBuilder();
			for (int i = 0, len = length - input.length(); i < len; i++) {
				sb.append(pad);
			}
			sb.append(input);
			return sb.toString();
		}
		return input;
	}

	/**
	 * Right pad a string with the specified character, if the string length is
	 * less then the specified length.
	 *
	 * @param input
	 * @param length
	 * @param pad
	 * @return right-padded string
	 */
	public static String rightPad(String input, int length, char pad) {
		if (input.length() < length) {
			StringBuilder sb = new StringBuilder();
			sb.append(input);
			for (int i = 0, len = length - input.length(); i < len; i++) {
				sb.append(pad);
			}
			return sb.toString();
		}
		return input;
	}

	/**
	 * Calculates the SHA1 of the string.
	 *
	 * @param text
	 * @return sha1 of the string
	 */
	public static String getSHA1(String text) {
		try {
			byte[] bytes = text.getBytes("iso-8859-1");
			return getSHA1(bytes);
		} catch (UnsupportedEncodingException u) {
			throw new RuntimeException(u);
		}
	}

	/**
	 * Calculates the SHA1 of the byte array.
	 *
	 * @param bytes
	 * @return sha1 of the byte array
	 */
	public static String getSHA1(byte[] bytes) {
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(bytes, 0, bytes.length);
			byte[] digest = md.digest();
			return toHex(digest);
		} catch (NoSuchAlgorithmException t) {
			throw new RuntimeException(t);
		}
	}

	/**
	 * Calculates the MD5 of the string.
	 *
	 * @param string
	 * @return md5 of the string
	 */
	public static String getMD5(String string) {
		try {
			return getMD5(string.getBytes("iso-8859-1"));
		} catch (UnsupportedEncodingException u) {
			throw new RuntimeException(u);
		}
	}

	/**
	 * Calculates the MD5 of the string.
	 *
	 * @param string
	 * @return md5 of the string
	 */
	public static String getMD5(byte [] bytes) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.reset();
			md.update(bytes);
			byte[] digest = md.digest();
			return toHex(digest);
		} catch (NoSuchAlgorithmException t) {
			throw new RuntimeException(t);
		}
	}

	/**
	 * Returns the hex representation of the byte array.
	 *
	 * @param bytes
	 * @return byte array as hex string
	 */
	public static String toHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length * 2);
		for (int i = 0; i < bytes.length; i++) {
			if ((bytes[i] & 0xff) < 0x10) {
				sb.append('0');
			}
			sb.append(Long.toString(bytes[i] & 0xff, 16));
		}
		return sb.toString();
	}

	/**
	 * Returns the root path of the specified path. Returns a blank string if
	 * there is no root path.
	 *
	 * @param path
	 * @return root path or blank
	 */
	public static String getRootPath(String path) {
		if (path.indexOf('/') > -1) {
			return path.substring(0, path.lastIndexOf('/'));
		}
		return "";
	}

	/**
	 * Returns the path remainder after subtracting the basePath from the
	 * fullPath.
	 *
	 * @param basePath
	 * @param fullPath
	 * @return the relative path
	 */
	public static String getRelativePath(String basePath, String fullPath) {
		String bp = basePath.replace('\\', '/').toLowerCase();
		String fp = fullPath.replace('\\', '/').toLowerCase();
		if (fp.startsWith(bp)) {
			String relativePath = fullPath.substring(basePath.length()).replace('\\', '/');
			if (relativePath.length() > 0 && relativePath.charAt(0) == '/') {
				relativePath = relativePath.substring(1);
			}
			return relativePath;
		}
		return fullPath;
	}

	/**
	 * Splits the space-separated string into a list of strings.
	 *
	 * @param value
	 * @return list of strings
	 */
	public static List<String> getStringsFromValue(String value) {
		return getStringsFromValue(value, " ");
	}

	/**
	 * Splits the string into a list of string by the specified separator.
	 *
	 * @param value
	 * @param separator
	 * @return list of strings
	 */
	public static List<String> getStringsFromValue(String value, String separator) {
        List<String> strings = new ArrayList<String>();
        try {
            String[] chunks = value.split(separator + "(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
            for (String chunk : chunks) {
                chunk = chunk.trim();
                if (chunk.length() > 0) {
                    if (chunk.charAt(0) == '"' && chunk.charAt(chunk.length() - 1) == '"') {
                        // strip double quotes
                        chunk = chunk.substring(1, chunk.length() - 1).trim();
                    }
                    strings.add(chunk);
                }
            }
        } catch (PatternSyntaxException e) {
            throw new RuntimeException(e);
        }
        return strings;
    }

	/**
	 * Validates that a name is composed of letters, digits, or limited other
	 * characters.
	 *
	 * @param name
	 * @return the first invalid character found or null if string is acceptable
	 */
	public static Character findInvalidCharacter(String name) {
		char[] validChars = { '/', '.', '_', '-', '~', '+' };
		for (char c : name.toCharArray()) {
			if (!Character.isLetterOrDigit(c)) {
				boolean ok = false;
				for (char vc : validChars) {
					ok |= c == vc;
				}
				if (!ok) {
					return c;
				}
			}
		}
		return null;
	}

	/**
	 * Simple fuzzy string comparison. This is a case-insensitive check. A
	 * single wildcard * value is supported.
	 *
	 * @param value
	 * @param pattern
	 * @return true if the value matches the pattern
	 */
	public static boolean fuzzyMatch(String value, String pattern) {
		if (value.equalsIgnoreCase(pattern)) {
			return true;
		}
		if (pattern.contains("*")) {
			boolean prefixMatches = false;
			boolean suffixMatches = false;

			int wildcard = pattern.indexOf('*');
			String prefix = pattern.substring(0, wildcard).toLowerCase();
			prefixMatches = value.toLowerCase().startsWith(prefix);

			if (pattern.length() > (wildcard + 1)) {
				String suffix = pattern.substring(wildcard + 1).toLowerCase();
				suffixMatches = value.toLowerCase().endsWith(suffix);
				return prefixMatches && suffixMatches;
			}
			return prefixMatches || suffixMatches;
		}
		return false;
	}

	/**
	 * Compare two repository names for proper group sorting.
	 *
	 * @param r1
	 * @param r2
	 * @return
	 */
	public static int compareRepositoryNames(String r1, String r2) {
		// sort root repositories first, alphabetically
		// then sort grouped repositories, alphabetically
		r1 = r1.toLowerCase();
		r2 = r2.toLowerCase();
		int s1 = r1.indexOf('/');
		int s2 = r2.indexOf('/');
		if (s1 == -1 && s2 == -1) {
			// neither grouped
			return r1.compareTo(r2);
		} else if (s1 > -1 && s2 > -1) {
			// both grouped
			return r1.compareTo(r2);
		} else if (s1 == -1) {
			return -1;
		} else if (s2 == -1) {
			return 1;
		}
		return 0;
	}

	/**
	 * Sort grouped repository names.
	 *
	 * @param list
	 */
	public static void sortRepositorynames(List<String> list) {
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return compareRepositoryNames(o1, o2);
			}
		});
	}

	public static String getColor(String value) {
		int cs = 0;
		for (char c : getMD5(value.toLowerCase()).toCharArray()) {
			cs += c;
		}
		int n = (cs % 360);
		float hue = ((float) n) / 360;
		return hsvToRgb(hue, 0.90f, 0.65f);
	}

	public static String hsvToRgb(float hue, float saturation, float value) {
		int h = (int) (hue * 6);
		float f = hue * 6 - h;
		float p = value * (1 - saturation);
		float q = value * (1 - f * saturation);
		float t = value * (1 - (1 - f) * saturation);

		switch (h) {
		case 0:
			return rgbToString(value, t, p);
		case 1:
			return rgbToString(q, value, p);
		case 2:
			return rgbToString(p, value, t);
		case 3:
			return rgbToString(p, q, value);
		case 4:
			return rgbToString(t, p, value);
		case 5:
			return rgbToString(value, p, q);
		default:
			throw new RuntimeException(
					"Something went wrong when converting from HSV to RGB. Input was " + hue + ", "
							+ saturation + ", " + value);
		}
	}

	public static String rgbToString(float r, float g, float b) {
		String rs = Integer.toHexString((int) (r * 256));
		String gs = Integer.toHexString((int) (g * 256));
		String bs = Integer.toHexString((int) (b * 256));
		return "#" + rs + gs + bs;
	}

	/**
	 * Strips a trailing ".git" from the value.
	 *
	 * @param value
	 * @return a stripped value or the original value if .git is not found
	 */
	public static String stripDotGit(String value) {
		if (value.toLowerCase().endsWith(".git")) {
			return value.substring(0, value.length() - 4);
		}
		return value;
	}

	/**
	 * Count the number of lines in a string.
	 *
	 * @param value
	 * @return the line count
	 */
	public static int countLines(String value) {
		if (isEmpty(value)) {
			return 0;
		}
		return value.split("\n").length;
	}

	/**
	 * Returns the file extension of a path.
	 *
	 * @param path
	 * @return a blank string or a file extension
	 */
	public static String getFileExtension(String path) {
		int lastDot = path.lastIndexOf('.');
		if (lastDot > -1) {
			return path.substring(lastDot + 1);
		}
		return "";
	}

	/**
	 * Returns the file extension of a path.
	 *
	 * @param path
	 * @return a blank string or a file extension
	 */
	public static String stripFileExtension(String path) {
		int lastDot = path.lastIndexOf('.');
		if (lastDot > -1) {
			return path.substring(0, lastDot);
		}
		return path;
	}

	/**
	 * Replace all occurences of a substring within a string with
	 * another string.
	 *
	 * From Spring StringUtils.
	 *
	 * @param inString String to examine
	 * @param oldPattern String to replace
	 * @param newPattern String to insert
	 * @return a String with the replacements
	 */
	public static String replace(String inString, String oldPattern, String newPattern) {
		StringBuilder sb = new StringBuilder();
		int pos = 0; // our position in the old string
		int index = inString.indexOf(oldPattern);
		// the index of an occurrence we've found, or -1
		int patLen = oldPattern.length();
		while (index >= 0) {
			sb.append(inString.substring(pos, index));
			sb.append(newPattern);
			pos = index + patLen;
			index = inString.indexOf(oldPattern, pos);
		}
		sb.append(inString.substring(pos));
		// remember to append any characters to the right of a match
		return sb.toString();
	}

	/**
	 * Decodes a string by trying several charsets until one does not throw a
	 * coding exception.  Last resort is to interpret as UTF-8 with illegal
	 * character substitution.
	 *
	 * @param content
	 * @param charsets optional
	 * @return a string
	 */
	public static String decodeString(byte [] content, String... charsets) {
		Set<String> sets = new LinkedHashSet<String>();
		if (!ArrayUtils.isEmpty(charsets)) {
			sets.addAll(Arrays.asList(charsets));
		}
		String value = null;
		sets.addAll(Arrays.asList("UTF-8", "ISO-8859-1", Charset.defaultCharset().name()));
		for (String charset : sets) {
			try {
				Charset cs = Charset.forName(charset);
				CharsetDecoder decoder = cs.newDecoder();
				CharBuffer buffer = decoder.decode(ByteBuffer.wrap(content));
				value = buffer.toString();
				break;
			} catch (CharacterCodingException e) {
				// ignore and advance to the next charset
			} catch (IllegalCharsetNameException e) {
				// ignore illegal charset names
			} catch (UnsupportedCharsetException e) {
				// ignore unsupported charsets
			}
		}
		if (value != null && value.startsWith("\uFEFF")) {
			// strip UTF-8 BOM
            return value.substring(1);
        }
		return value;
	}

	/**
	 * Attempt to extract a repository name from a given url using regular
	 * expressions.  If no match is made, then return whatever trails after
	 * the final / character.
	 *
	 * @param regexUrls
	 * @return a repository path
	 */
	public static String extractRepositoryPath(String url, String... urlpatterns) {
		for (String urlPattern : urlpatterns) {
			Pattern p = Pattern.compile(urlPattern);
			Matcher m = p.matcher(url);
			while (m.find()) {
				String repositoryPath = m.group(1);
				return repositoryPath;
			}
		}
		// last resort
		if (url.lastIndexOf('/') > -1) {
			return url.substring(url.lastIndexOf('/') + 1);
		}
		return url;
	}

	/**
	 * Converts a string with \nnn sequences into a UTF-8 encoded string.
	 * @param input
	 * @return
	 */
	public static String convertOctal(String input) {
		try {
			ByteArrayOutputStream bytes = new ByteArrayOutputStream();
			Pattern p = Pattern.compile("(\\\\\\d{3})");
			Matcher m = p.matcher(input);
			int i = 0;
			while (m.find()) {
				bytes.write(input.substring(i, m.start()).getBytes("UTF-8"));
				// replace octal encoded value
				// strip leading \ character
				String oct = m.group().substring(1);
				bytes.write(Integer.parseInt(oct, 8));
				i = m.end();
			}
			if (bytes.size() == 0) {
				// no octal matches
				return input;
			} else {
				if (i < input.length()) {
					// add remainder of string
					bytes.write(input.substring(i).getBytes("UTF-8"));
				}
			}
			return bytes.toString("UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return input;
	}

	/**
	 * Returns the first path element of a path string.  If no path separator is
	 * found in the path, an empty string is returned.
	 *
	 * @param path
	 * @return the first element in the path
	 */
	public static String getFirstPathElement(String path) {
		if (path.indexOf('/') > -1) {
			return path.substring(0, path.indexOf('/')).trim();
		}
		return "";
	}

	/**
	 * Returns the last path element of a path string
	 *
	 * @param path
	 * @return the last element in the path
	 */
	public static String getLastPathElement(String path) {
		if (path.indexOf('/') > -1) {
			return path.substring(path.lastIndexOf('/') + 1);
		}
		return path;
	}

	/**
	 * Variation of String.matches() which disregards case issues.
	 *
	 * @param regex
	 * @param input
	 * @return true if the pattern matches
	 */
	public static boolean matchesIgnoreCase(String input, String regex) {
		Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(input);
		return m.matches();
	}

	/**
	 * Removes new line and carriage return chars from a string.
	 * If input value is null an empty string is returned.
	 *
	 * @param input
	 * @return a sanitized or empty string
	 */
	public static String removeNewlines(String input) {
		if (input == null) {
			return "";
		}
		return input.replace('\n',' ').replace('\r',  ' ').trim();
	}


	/**
	 * Encode the username for user in an url.
	 *
	 * @param name
	 * @return the encoded name
	 */
	public static String encodeUsername(String name) {
		return name.replace("@", "%40").replace(" ", "%20").replace("\\", "%5C");
	}

	/**
	 * Decode a username from an encoded url.
	 *
	 * @param name
	 * @return the decoded name
	 */
	public static String decodeUsername(String name) {
		return name.replace("%40", "@").replace("%20", " ").replace("%5C", "\\");
	}
}