package antipatternsrecovery.antipatterns;

import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

import antipatternsrecovery.beans.BeanConverter;
import antipatternsrecovery.beans.ClassBean;
import antipatternsrecovery.parsingElements.McCabeCC;

public class ComplexClass {
	private Vector<ClassBean> candidateComplexClasses;
	private McCabeCC cc;
	private IJavaProject projectToAnalyze;

	public ComplexClass(IJavaProject pProject){
		this.cc=new McCabeCC();
		this.candidateComplexClasses=new Vector<ClassBean>();
		this.projectToAnalyze=pProject;
	}

	public Vector<ClassBean> searchComplexClasses(){
		try {
			for(IPackageFragment pack: this.projectToAnalyze.getPackageFragments()) {
				for(ICompilationUnit cu: pack.getCompilationUnits()){
					for(IType type: cu.getTypes()){
						int mcCabe=cc.evaluate(type.getSource());
						int loc=this.LOC(type.getCompilationUnit());

						if((loc>1000) && (mcCabe>30)) {
							ClassBean newClass=BeanConverter.softCastCUToClassBean(type.getCompilationUnit());
							if(! this.isIn(newClass))
								this.candidateComplexClasses.add(newClass);
						}
					}
				}
			}
		} catch (JavaModelException e) {
			return this.candidateComplexClasses;
		}

		return this.candidateComplexClasses;
	}

	private int LOC(ICompilationUnit pClass){
		int loc=0;
		try {
			String source=pClass.getSource();
			String regex="[\n]";
			Pattern pattern=Pattern.compile(regex);
			Matcher matcher = pattern.matcher(source);
			while (matcher.find()) 
				loc++;		    
		} catch (JavaModelException e) {
			e.printStackTrace();
		}
		return loc+1;
	}

	private boolean isIn(ClassBean pClassBean){
		for(ClassBean cb: this.candidateComplexClasses) {
			if(cb.getName().equals(pClassBean.getName()))
				return true;
		}
		return false;
	}

	public String toString() { 
		String toReturn="";
		for(ClassBean classBean: this.candidateComplexClasses){
			if(classBean.getBelongingPackage()!=null)
				toReturn+=classBean.getName()+"; " +classBean.getBelongingPackage().getName()+";\n";
			else 
				toReturn+=classBean.getName()+";\n";
		}
		return toReturn;
	}
}
