/*******************************************************************************
 * Copyright (c) 2000, 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 API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.util;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 *
 */
public class PatternConstructor {
	

	private PatternConstructor() {
		// don't instantiate
	}

	/**
	 * Creates a pattern element from the pattern string which is either a reg-ex expression or in our old
	 * 'StringMatcher' format.
	 * @param pattern The search pattern
	 * @param isCaseSensitive Set to <code>true</code> to create a case insensitive pattern
	 * @param isRegexSearch <code>true</code> if the passed string already is a reg-ex pattern
	 * @return The created pattern
	 * @throws PatternSyntaxException
	 */
	public static Pattern createPattern(String pattern, boolean isCaseSensitive, boolean isRegexSearch) throws PatternSyntaxException {
		if (!isRegexSearch) {
			pattern=  asRegEx(pattern, new StringBuffer()).toString();			
		}
		
		if (!isCaseSensitive)
			return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.MULTILINE);
		
		return Pattern.compile(pattern, Pattern.MULTILINE);
	}
	
	/**
	 * Creates a pattern element from the pattern string which is either a reg-ex expression or in our old
	 * 'StringMatcher' format.
	 * @param patterns The search patterns
	 * @param isCaseSensitive Set to <code>true</code> to create a case insensitive pattern
	 * @param isRegexSearch <code>true</code> if the passed string already is a reg-ex pattern
	 * @return The created pattern
	 * @throws PatternSyntaxException
	 */
	public static Pattern createPattern(String[] patterns, boolean isCaseSensitive, boolean isRegexSearch) throws PatternSyntaxException {
		StringBuffer pattern= new StringBuffer();
		for (int i= 0; i < patterns.length; i++) {
			if (i > 0) {
				pattern.append('|');
			}
			if (isRegexSearch) {
				pattern.append(patterns[i]);
			} else {
				asRegEx(patterns[i], pattern);
			}
		}
		return createPattern(pattern.toString(), isCaseSensitive, true);
	}
	
	
	/**
	 * Translates a StringMatcher pattern (using '*' and '?') to a regex pattern string
	 * @param stringMatcherPattern a pattern using '*' and '?'
	 */
	private static StringBuffer asRegEx(String stringMatcherPattern, StringBuffer out) {	
		boolean escaped= false;
		boolean quoting= false;
		
		int i= 0;
		while (i < stringMatcherPattern.length()) {
			char ch= stringMatcherPattern.charAt(i++);
			
			if (ch == '*' && !escaped) {
				if (quoting) {
					out.append("\\E"); //$NON-NLS-1$
					quoting= false;
				}
				out.append(".*"); //$NON-NLS-1$
				escaped= false;
				continue;
			} else if (ch == '?' && !escaped) {
				if (quoting) {
					out.append("\\E"); //$NON-NLS-1$
					quoting= false;
				}
				out.append("."); //$NON-NLS-1$
				escaped= false;
				continue;
			} else if (ch == '\\' && !escaped) {
				escaped= true;
				continue;								
				
			} else if (ch == '\\' && escaped) {
				escaped= false;
				if (quoting) {
					out.append("\\E"); //$NON-NLS-1$
					quoting= false;
				}
				out.append("\\\\"); //$NON-NLS-1$
				continue;								
			}
			
			if (!quoting) {
				out.append("\\Q"); //$NON-NLS-1$
				quoting= true;
			}
			if (escaped && ch != '*' && ch != '?' && ch != '\\')
				out.append('\\');
			out.append(ch);
			escaped= ch == '\\';
			
		}
		if (quoting)
			out.append("\\E"); //$NON-NLS-1$
		
		return out;
	}

}
