package models;

import models.algebra.Symbol;
import models.algebra.Type;

public abstract class EvaluatableTerm extends RDLTerm{

	public EvaluatableTerm(Symbol symbol, int order) {
		super(symbol, order);
	}
	
	public abstract boolean isLinearRightNormal();
	
	public abstract EvaluatableTerm linearRightNormalize();
	public abstract void selfLinearRightNormalize();
	
	public static ResourceVariable of(String name, Type type, int order) {
		return new ResourceVariable(name, type, order);
	}
	
	public static DependencyTerm of(EvaluatableTerm term, ResourceVariable variable, EvaluatableTerm valueTerm) {
		return new DependencyTerm(new Dependency(term, variable), valueTerm);
	}
	
	public static EvaluatableTerm of(EvaluatableTerm term, ResourceVariable variable, EvaluatableTerm valueTerm, int order) {
		if(variable.getOrder() == valueTerm.getOrder() && variable.getOrder() == order) {
			return new DependencyTerm(new Dependency(term, variable), valueTerm);
		} else if(variable.getOrder() -1 == order) {
			return new DependencyTerm(new Dependency(term, variable), valueTerm);
		} else {
			return new SetEvaluatableTerm(new DependencyTerm(new Dependency(term, variable), valueTerm), order);
		}
	}
	
	public static DependencyTerm of(Dependency dependency, EvaluatableTerm argumentTerm) {
		return new DependencyTerm(dependency, argumentTerm);
	}
	
	public static EvaluatableTerm of(Dependency dependency, EvaluatableTerm argumentTerm, int order) {
		ResourceVariable variable = dependency.getDependedVariable();
		if(variable.getOrder() == argumentTerm.getOrder() && variable.getOrder() == order) {
			return new DependencyTerm(dependency, argumentTerm);
		} else if(variable.getOrder() - 1 == order) {
			return new DependencyTerm(dependency, argumentTerm);
		} else {
			return new SetEvaluatableTerm(new DependencyTerm(dependency, argumentTerm), order); 
		}
	}
	 
	public static SetEvaluatableTerm of(EvaluatableTerm term, int order) {
		return new SetEvaluatableTerm(term, order);
	}
	
}
