package Smells;

import java.io.BufferedWriter;
import java.util.List;

import org.eclipse.jdt.core.dom.TypeDeclaration;

import Analysis.printer;
import Detectors.THRESHOLDS;

public class LargeClass extends Smell {
	public static int totalNoOfDetectorSmells=0;
	public static int totalNoOfDisparedSmells=0;
	String Suggestion="Decompose it into smaller ones (Menu Refactor-->Extract Class)";
	public LargeClass() {
		setType(SMELLTYPE.LARGECLASS);
	}
	public String getSuggestion()
	{
		return Suggestion;
		
		
	}
	
	public static void AdjustThresholdAfterStatistics()
	{
		double RATION;
		if(totalNoOfDetectorSmells<=10)return;
		
	 RATION=totalNoOfDisparedSmells/totalNoOfDetectorSmells;
		if(! THRESHOLDS.IsOurOfRange( RATION))
		{ THRESHOLDS.setLARGECLASS_LINES(THRESHOLDS.AdjustThreshold(THRESHOLDS.getLARGECLASS_LINES(),  RATION));}
		 totalNoOfDetectorSmells=0;
		 totalNoOfDisparedSmells=0;
	}
	@Override
	public boolean Smellequal(Smell obj) {
		if (!(obj instanceof Smell))
			return false;
		Smell target = (Smell) obj;
		if (target == null)
			return false;
		// if(target.unit!=this.unit) return false;
		if (target.getType() != this.getType())
			return false;

		TypeDeclaration targetType = (TypeDeclaration) target.associatedNode;
		TypeDeclaration thisType = (TypeDeclaration) associatedNode;
		String targetTypeName = targetType.getName().getFullyQualifiedName()
				.trim();
		String thisTypeName = thisType.getName().getFullyQualifiedName().trim();
		if (targetTypeName.compareToIgnoreCase(thisTypeName) != 0)
			return false;
		return true;
	}
	public void save(BufferedWriter bw)
	{   
	  
		
		String filelocation=this.resource.getLocation().toString();
		
		
		
		try{ 
			 bw.newLine();
			 bw.append(SMELLTYPE.getText(this.getType()));
			 bw.append(THRESHOLDS.tab);
			 bw.append(filelocation);
			 bw.append(THRESHOLDS.tab);
			 bw.append(Long.toString(this.appearTime));
			 bw.append(THRESHOLDS.tab);
	     if (!(this.associatedNode instanceof TypeDeclaration))  // obj是否是TypeDeclaration的一个实例
				return;// failed
			TypeDeclaration typeDec = (TypeDeclaration) this.associatedNode;
			bw.append(typeDec.getName().toString());
		}
			catch(Exception e) {
  	     printer.print(e); }
		
		
	}
	public void forcomparation()
	{
		  if (!(this.associatedNode instanceof TypeDeclaration))  // obj是否是TypeDeclaration的一个实例
				return;// failed
			TypeDeclaration typeDec = (TypeDeclaration) this.associatedNode;
			forcompareted=typeDec.getName().toString();
		}
		
		
		
		
		
		
		
	
	private static int totalSmellsWithCurrentThreshold = 0;
	private static int totalRemovedSemllsWithCurrentThreshold = 0;

	@Override
	public void toBeRmoved() {
		if (this.DetectedWithCurrentThreshold) {
			totalRemovedSemllsWithCurrentThreshold++;
		}
	}

	@Override
	public void CountNewSmell() {
		if (this.DetectedWithCurrentThreshold) {
			totalSmellsWithCurrentThreshold++;
		}
	}

	public static boolean adjustThreshold(List<Smell> existing) {
		printer.println("Total Semlls: " + totalSmellsWithCurrentThreshold);
		printer.println("Resovled Semlls: "
				+ totalRemovedSemllsWithCurrentThreshold);
		if (totalSmellsWithCurrentThreshold == 0)
			return false;
		double ratio = totalRemovedSemllsWithCurrentThreshold
				/ (double) totalSmellsWithCurrentThreshold;
		if (!THRESHOLDS.IsOurOfRange(ratio)) {
			return false; // no need to adjust the threshold
		}
		THRESHOLDS.setLARGECLASS_LINES(THRESHOLDS.AdjustThreshold(
				THRESHOLDS.getLARGECLASS_LINES(), ratio));

		// TODO 重新检查smell
		for (Smell asmell : existing) {
			if (asmell instanceof LargeClass)
				asmell.DetectedWithCurrentThreshold = false;
		}
		totalSmellsWithCurrentThreshold = 0;
		totalRemovedSemllsWithCurrentThreshold = 0;
		return true;
	}

	/*public void Save2File(BufferedWriter bw) {

		String name = getFullyQualifiedName((TypeDeclaration) associatedNode);

		try {
		     
		     bw.append("LargeClass ");
		   
		     bw.append(name);
		     bw.newLine();
		     
		} 

		catch (Exception e) {
		}

	}*/

	/*private static String getFullyQualifiedName(final TypeDeclaration type) {
		String name = type.getName().getFullyQualifiedName();
		final CompilationUnit root = (CompilationUnit) type.getRoot();
		for (ASTNode t = type.getParent(); t != root; t = t.getParent()) {
			name = ((TypeDeclaration) t).getName().getFullyQualifiedName()
					+ '$' + name;
		}

		if (root.getPackage() != null) {
			final String packageName = root.getPackage().getName()
					.getFullyQualifiedName();
			name = packageName + '.' + name;
		}
		return name;
	}*/
}
