package be.jeffcheasey88.peeratcode.parser.java;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import be.jeffcheasey88.peeratcode.parser.java.CleanerPool.Cleaner;
import be.jeffcheasey88.peeratcode.parser.java.operations.OperationContainer;

public class Function extends OperationContainer{
	
	private static Pattern PATTERN = Pattern.compile("^(\\s*([^(]*)\\(([^)]*)\\)\\s*([^{]*)\\{)(.*)$");
	
	private int modifier;
	private String returnType;
	private String name;
	private List<Variable> parameters;
	private String exceptions;
	
	private boolean constructor;
	
	public Function(){
		this.parameters = new ArrayList<>();
	}
	
	public int parse(String content, CleanerPool cleaner) throws Exception{
		Matcher matcher = PATTERN.matcher(content);
		matcher.matches();
		
		attribute(matcher.group(2));
		parameters(matcher.group(3)+";", cleaner);
		this.exceptions = matcher.group(4).trim();
		
		CleanerPool generic = new CleanerPool(new Cleaner("GENERIC_FUNCTION", '{', '}'));
		String zip = generic.clean("{"+matcher.group(5));
		String body = generic.unzipOne(zip, (s,p) -> s);
		String unzip = body.substring(1, body.indexOf('}'));
		System.out.println("----------Before------------");
		show(0);
		System.out.println("----------------------------");
		parse(unzip, cleaner, generic);
		System.out.println("----------After------------");
		show(0);
		System.out.println("---------------------------");
		
		return matcher.group(1).length()+generic.unzip(unzip, ((s,p) -> s)).length()+1;
	}
	
	private static Pattern UNZIP_STICK = Pattern.compile("\\s+(?<e>[<|(|\\[|\"|'])");
	private static Pattern UNZIP_MAJ = Pattern.compile(">(?<e>[^>\\d,;(])");
	private static Pattern UNZIP_ARRAY = Pattern.compile("](?<e>[^\\[\\d,;])");
	
	private void attribute(String content){
		CleanerPool generic = new CleanerPool(
				new Cleaner("GENERIC_TYPE_",'<','>'),
				new Cleaner("GENERIC_ARRAY",'[',']'));
		String zip = generic.clean(content);
		String unzip = generic.unzip(zip, (value, pattern) -> {
			return value.replaceAll("\\s+", "");
		});
		
		unzip = UNZIP_STICK.matcher(unzip).replaceAll("${e}");
		unzip = UNZIP_MAJ.matcher(unzip).replaceAll("> ${e}");
		unzip = UNZIP_ARRAY.matcher(unzip).replaceAll("] ${e}");
		
		Iterator<String> values = new ArrayIterator<>(unzip.split("\\s+"));
		String value = null;
		int modifier;
		while(values.hasNext() && (modifier = JavaParser.getModifier(value = values.next())) > 0){
			this.modifier+=modifier;
		}
		if(this.returnType == null){
			this.returnType = value;
			if(values.hasNext()) value = values.next();
			else constructor = true;
		}
		if(this.name == null){
			this.name = value;
		}
	}
	
	private void parameters(String content, CleanerPool cleaner) throws Exception{
		if(content.length() == 1) return;
		boolean quote = false;
		do {
			Variable variable = new Variable();
			int index = variable.parse(content, cleaner);
			this.parameters.add(variable);
			content = content.substring(index);
			quote = content.startsWith(",");
			if(quote) content = content.substring(1);
		}while(quote);
	}
	
	public void show(int tab){
		String start = "";
		for(int i = 0; i < tab; i++) start+="\t";
		String param = "";
		for(Variable v : this.parameters) param+=","+v.getType()+" "+v.getName()+"";
		if(!param.isEmpty()) param = param.substring(1);
		System.out.println(start+Modifier.toString(modifier)+" "+(constructor ? "" : returnType+" ")+name+"("+param+") "+exceptions+"{");
		for(JavaElement child : getChilds()) child.show(tab+1);
		System.out.println(start+"}");
	}
}
