package eu.dnetlib.data.collective.transformation.rulelanguage;

import java.util.Properties;

import eu.dnetlib.data.collective.transformation.core.schema.SchemaElement;
import eu.dnetlib.data.collective.transformation.rulelanguage.util.FunctionCall;

/**
 * @author jochen
 *
 */
public class Rules implements Comparable<Rules>, IRule{

	public static final String staticRule = "static";
	private String attribute = "";
	private String targetField = "";
	private String ruleDeclaration = "";
	private String xpath = "";
	private String constant = "";
	private String namespace = "";
	private String variable = "";
	private String template = "";
	private String templateMatch = "";
	private FunctionCall funcCall;
	private Condition condition;
	private boolean isEmpty = false;
	private boolean isSkip = false;
	private SchemaElement targetSchemaElement;
	private String assignmentVariable = "";
	private RulesSet rulesSet;
	private Properties properties = new Properties();
	
	public Rules() {
	}
				
	/**
	 * indicates if the rule is declared as static
	 * @return true if static, false otherwise
	 */
	public boolean isStatic(){
		if (ruleDeclaration.equals(staticRule)){
			return true;
		}
		return false;
	}
	
	/**
	 * indicates if the rule defines a variable
	 * @return true if variable is defined, false otherwise
	 * @see eu.dnetlib.data.collective.transformation.rulelanguage.IRule#definesVariable()
	 */
	public boolean definesVariable(){
		if (variable.length() > 0) return true;
		return false;
	}
	
	public boolean definesTargetField(){
		if (targetField.length() > 0) return true;
		return false;
	}
	
	/**
	 * checks if this rule defines an attribute
	 * @return true if defines attribute else false
	 */
	public boolean definesAttribute(){
		if (attribute.length() > 0) return true;
		return false;
	}
	
	public boolean definesTemplate(){
		if (template.length() > 0) return true;
		return false;
	}
	
	@Override
	public boolean definesTemplateMatch() {
		if (templateMatch.length() > 0) return true;
		return false;
	}
	
	public void setXpath(String xpath) {
		this.xpath = xpath;
	}
	public String getXpath() {
		return xpath;
	}
	
	/**
	 * sets the argument aVariable as the value of the rule
	 * @param aVariable the variable as a reference to the value
	 */
	public void setAssignmentVariable(String aVariable){
		this.assignmentVariable = aVariable;
	}
	
	public String getAssignmentVariable(){
		return this.assignmentVariable;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public String getNamespace() {
		return namespace;
	}

	public void setConstant(String constant) {
		this.constant = constant;
	}

	public String getConstant() {
		return constant;
	}
	
	@Deprecated
	public void setTargetField(String targetField) {
		if (this.variable.length() > 0){
			throw new IllegalStateException("Invalid rule definition: a rule is either defined as an output element or as a variable");
		}
		this.targetField = targetField;
	}

	/*
	 * @deprecated replaced by {@Link #getUniqueName()}
	 */
	@Deprecated
	public String getTargetField() {
		return targetField;
	}
	
	public void setRuleDeclaration(String ruleDeclaration) {
		this.ruleDeclaration = ruleDeclaration;
	}

	public String getRuleDeclaration() {
		return ruleDeclaration;
	}
		
	/*
	 * compares two rules objects based on their xpath, function and namespace names
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(Rules o) {
		if (
			o.targetField.equals(this.targetField) &&
			o.variable.equals(this.variable) &&
			o.template.equals(this.template) &&
			o.templateMatch.equals(this.templateMatch) &&
			o.ruleDeclaration.equals(this.ruleDeclaration) &&
			o.namespace.equals(this.namespace) &&
			o.constant.equals(this.constant) &&
			o.xpath.equals(this.xpath)){
			return 0;			
		}else{
			return -1;
		}
	}

	public void setFunctionCall(FunctionCall funcCall) {
		this.funcCall = funcCall;
	}

	public FunctionCall getFunctionCall() {
		return funcCall;
	}

	@Override
	public String getUniqueName() {
		if (this.definesVariable()) return this.variable;
		else if (this.definesTemplate()) return this.template;
		return this.targetField;
	}

	@Override
	public boolean hasCondition() {
		if (condition != null) return true;
		return false;
	}

	/**
	 * @return the condition
	 */
	public Condition getCondition() {
		return condition;
	}

	/**
	 * @param condition the condition to set
	 */
	public void setCondition(Condition condition) {
		this.condition = condition;
	}

	/**
	 * @param variable the variable to set
	 */
	public void setVariable(String variable) {
		if (this.targetField.length() > 0){
			throw new IllegalStateException("Invalid rule definition: a rule is either defined as an output element or as a variable");
		}
		this.variable = variable;
	}

	/**
	 * @return the variable
	 */
	public String getVariable() {
		return variable;
	}

	/**
	 * @param isEmpty the isEmpty to set
	 */
	public void setEmpty(boolean isEmpty) {
		this.isEmpty = isEmpty;
	}

	/**
	 * @return the isEmpty
	 */
	public boolean isEmpty() {
		return isEmpty;
	}
	
	/**
	 * @param targetSchemaElement the targetSchemaElement to set
	 */
	public void setTargetSchemaElement(SchemaElement targetSchemaElement) {
		this.targetSchemaElement = targetSchemaElement;
	}

	/**
	 * @return the targetSchemaElement
	 */
	public SchemaElement getTargetSchemaElement() {
		return targetSchemaElement;
	}

	/**
	 * @return the template
	 */
	public String getTemplate() {
		return template;
	}

	/**
	 * @param template the template to set
	 */
	public void setTemplate(String template) {
		this.template = template;
	}

	/**
	 * @return the attribute
	 */
	public String getAttribute() {
		return attribute;
	}

	/**
	 * @param attribute the attribute to set
	 */
	public void setAttribute(String attribute) {
		this.attribute = attribute;
	}

	/**
	 * @return the rulesSet
	 */
	public RulesSet getRulesSet() {
		return rulesSet;
	}

	/**
	 * @param rulesSet the rulesSet to set
	 */
	public void setRulesSet(RulesSet rulesSet) {
		this.rulesSet = rulesSet;
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.data.collective.transformation.rulelanguage.IRule#hasSet()
	 */
	@Override
	public boolean hasSet() {
		if (rulesSet != null) return true;
		return false;
	}

	public String getTemplateMatch() {
		return templateMatch;
	}

	public void setTemplateMatch(String templateMatch) {
		this.templateMatch = templateMatch;
	}

	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	public boolean isSkip() {
		return isSkip;
	}

	public void setSkip(boolean isSkip) {
		this.isSkip = isSkip;
	}

}
