package com.cflint.plugins.core;

import ro.fortsoft.pf4j.Extension;
import cfml.parsing.cfscript.script.CFFuncDeclStatement;
import cfml.parsing.cfscript.script.CFFunctionParameter;
import cfml.parsing.cfscript.script.CFScriptStatement;

import com.cflint.BugInfo;
import com.cflint.BugList;
import com.cflint.plugins.CFLintScannerAdapter;
import com.cflint.plugins.Context;

import java.util.regex.Pattern;

import net.htmlparser.jericho.Element;

@Extension
public class ArgumentNameChecker extends CFLintScannerAdapter {
	final String severity = "INFO";
		
	@Override
	public void expression(final CFScriptStatement expression, final Context context, final BugList bugs) {
		if (expression instanceof CFFuncDeclStatement) {
			final CFFuncDeclStatement function = (CFFuncDeclStatement) expression;
			final int lineNo = function.getLine() + context.startLine() - 1;

			for (final CFFunctionParameter argument : function.getFormals()) {
				checkNameForBugs(argument.getName(), context.getFilename(), lineNo, bugs);
			}
		}
	}

	@Override
	public void element(final Element element, final Context context, final BugList bugs) {
		if (element.getName().equals("cfargument")) {
			final int lineNo = context.startLine();
			final String name = element.getAttributeValue("name");

			checkNameForBugs(name, context.getFilename(), lineNo, bugs);
		}
	}

	public void checkNameForBugs(String argument, String filename, int line, BugList bugs) {
		int minArgLength = ValidName.MIN_ARGUMENT_LENGTH;
		int maxArgLength = ValidName.MAX_ARGUMENT_LENGTH;
		int maxArgWords = ValidName.MAX_ARGUMENT_WORDS;

		if (getParameter("MinLength") != null) {
			try {
				minArgLength = Integer.parseInt(getParameter("MinLength"));
			} catch(Exception e) {}
		}

		if (getParameter("MaxLength") != null) {
			try {
				maxArgLength = Integer.parseInt(getParameter("MaxLength"));
			} catch(Exception e) {}
		}

		if (getParameter("MaxWords") != null) {
			try {
				maxArgWords = Integer.parseInt(getParameter("MaxWords"));
			} catch(Exception e) {}
		}

		ValidName name = new ValidName(minArgLength, maxArgLength, maxArgWords);

		if (name.isInvalid(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_INVALID_NAME")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument " + argument + " is not a valid name. Please use CamelCase or underscores.")
				.build());
		}
		if (name.isUpperCase(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_ALLCAPS_NAME")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument " + argument + " should not be upper case.")
				.build());
		}
		if (name.tooShort(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_TOO_SHORT")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument " + argument + " should be longer than " + minArgLength + " characters.")
				.build());
		}
		if (name.tooLong(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_TOO_LONG")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument " + argument + " should be shorter than " + maxArgLength + " characters.")
				.build());
		}
		if (!name.isUpperCase(argument) && name.tooWordy(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_TOO_WORDY")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument " + argument + " is too wordy, can you think of a more concise name?")
				.build());
		}
		if (name.isTemporary(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_IS_TEMPORARY")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Temporary argument " + argument + " could be named better.")
				.build());
		}
		if (name.hasPrefixOrPostfix(argument)) {
			bugs.add(new BugInfo.BugInfoBuilder().setLine(line).setMessageCode("ARGUMENT_HAS_PREFIX_OR_POSTFIX")
				.setSeverity(severity).setFilename(filename)
				.setMessage("Argument has prefix or postfix " + argument + " and could be named better.")
				.build());
		}
	}
}
@@ -989,32 +989,59 @@
 t.getFilename(),
+ context.getFunctionName(),
  lineNo, bugs);%0A
@@ -1347,24 +1347,51 @@
 tFilename(),
+ context.getFunctionName(),
  lineNo, bug
@@ -1465,16 +1465,37 @@
 ilename,
+ String functionName,
  int lin
@@ -2354,32 +2354,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -2682,32 +2682,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -2972,32 +2972,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -3289,32 +3289,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -3640,32 +3640,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -3962,32 +3962,58 @@
 lename(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMessage
@@ -4285,24 +4285,50 @@
 me(filename)
+.setFunction(functionName)
 %0A%09%09%09%09.setMes

add function name to bug info