package railo.runtime.rest.path;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import railo.runtime.type.Struct;


public class ExpressionPath extends Path {
	
	private Pattern pattern;
	private List<String> variables;

	public ExpressionPath(Pattern pattern, List<String> variables) {
		this.pattern=pattern;
		this.variables=variables;
	}

	public static Path getInstance(String path) {
		/*
		 TODO  handle if a pattern already has defined a group 
		 */
		
		int last=-1,startIndex,endIndex=0,index;
		String content,variableName,regexPart;
		StringBuilder regex=new StringBuilder();
		List<String> variables=new ArrayList<String>();
		while((startIndex=path.indexOf('{',last))!=-1){
			if(last+1<startIndex) {
				delimiter(variables,regex,path.substring(last+1,startIndex));
			}
				
			endIndex=path.indexOf('}',startIndex+1);
			if(endIndex==-1) return new LiteralPath(path);
			
			content=path.substring(startIndex+1,endIndex);
			index=content.indexOf(':');
			if(index!=-1) {
				variableName=content.substring(0,index).trim();
				regexPart=content.substring(index+1).trim();
			}
			else {
				variableName=content.trim();
				regexPart=".+";
			}
			regex.append('(');
			regex.append(regexPart);
			regex.append(')');
			variables.add(variableName);
			//print.e(variableName);
			//print.e(regexPart);
			last=endIndex;
		}
		
		if(endIndex+1<path.length())
			delimiter(variables,regex,path.substring(endIndex+1));
		
		//regex.append("(.*)");
		
		Pattern pattern=Pattern.compile(regex.toString());
		//print.e(regex);
		//print.e(variables);
		return new ExpressionPath(pattern,variables);
	}
	

	private static void delimiter(List<String> variables, StringBuilder regex, String delimiter) {
		variables.add(null);
		regex.append('(');
		/*print.e(delimiter+":"+Pattern.quote(delimiter));
		StringBuilder sb=new StringBuilder();
		int len=delimiter.length();
		char c;
		for (int i=0; i<len; i++) {
			c=delimiter.charAt(i);
			switch(c){
			case '.': sb.append("\\.");break;
			case '?': sb.append("\\?");break;
			case '\\': sb.append("\\\\");break;
			case '^': sb.append("\\^");break;
			case '$': sb.append("\\$");break;
			case '+': sb.append("\\+");break;
			default: sb.append(c);
			break;
			}
		}*/
		
		regex.append(Pattern.quote(delimiter));
		regex.append(')');
	}

	@Override
	public boolean match(Struct result,String path) {
		String var;
		Matcher m = pattern.matcher(path);
		boolean hasMatches=m.find();
		if(!hasMatches) return false;
		
		if (hasMatches) {
		    // Get all groups for this match
			int len=m.groupCount();
		    for (int i=1; i<=len; i++) {
		        String groupStr = m.group(i);
		        var = variables.get(i-1);
		        if(var!=null) result.setEL(var, groupStr.trim());
		    }
		}
		
		return true;
	}
	
	/*public static void main(String[] args) {
		Path path = getInstance("{aaa : \\d+}-{b}");
		print.e("+++++++++++");
		Map<String,String> res=new HashMap<String, String>();
		print.e(path.match(res,"1234-cd"));
		print.e(res);
	}*/
	

	
	public String toString(){
		return "expression:"+pattern.pattern();
	}
}
