package de.dhbwstuttgart.typeinference.unify.interfaces;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;

/**
 * Contains the inference rules that are applied to the set Eq.
 * @author Florian Steurer
 */
public interface IRuleSet {
	
	public Optional<UnifyPair> reduceUp(UnifyPair pair);
	public Optional<UnifyPair> reduceLow(UnifyPair pair);
	public Optional<UnifyPair> reduceUpLow(UnifyPair pair);
	public Optional<Set<UnifyPair>> reduceExt(UnifyPair pair, IFiniteClosure fc);
	public Optional<Set<UnifyPair>> reduceSup(UnifyPair pair, IFiniteClosure fc);
	public Optional<Set<UnifyPair>> reduceEq(UnifyPair pair);
	public Optional<Set<UnifyPair>> reduce1(UnifyPair pair, IFiniteClosure fc);
	public Optional<Set<UnifyPair>> reduce2(UnifyPair pair);
	
	/*
	 * Missing Reduce-Rules for Wildcards
	 */
	public Optional<UnifyPair> reduceWildcardLow(UnifyPair pair);
	public Optional<UnifyPair> reduceWildcardLowRight(UnifyPair pair);
	public Optional<UnifyPair> reduceWildcardUp(UnifyPair pair);
	public Optional<UnifyPair> reduceWildcardUpRight(UnifyPair pair);
	
	/*
	 * vgl. JAVA_BSP/Wildcard6.java
	public Optional<UnifyPair> reduceWildcardLowUp(UnifyPair pair);
	public Optional<UnifyPair> reduceWildcardUpLow(UnifyPair pair);
	public Optional<UnifyPair> reduceWildcardLeft(UnifyPair pair);
	 */
	
	/*
	 * Additional Rules which replace cases of the cartesian product
	 */
	
	/**
	 * Rule that replaces the fourth case of the cartesian product where (a <.? Theta)
	 */
	public Optional<UnifyPair> reduceTph(UnifyPair pair);
	
	/**
	 * Rule that replaces the sixth case of the cartesian product where (? ext Theta <.? a)
	 */
	public Optional<Set<UnifyPair>> reduceTphExt(UnifyPair pair);
	
	/**
	 * Rule that replaces the fourth case of the cartesian product where (? sup Theta <.? a)
	 */
	public Optional<Set<UnifyPair>> reduceTphSup(UnifyPair pair);
	
	/*
	 * FunN Rules
	 */
	public Optional<Set<UnifyPair>> reduceFunN(UnifyPair pair);
	public Optional<Set<UnifyPair>> greaterFunN(UnifyPair pair, IFiniteClosure fc);
	public Optional<Set<UnifyPair>> smallerFunN(UnifyPair pair,  IFiniteClosure fc);
	public Optional<Set<UnifyPair>> reduceFIFunN(UnifyPair pair, IFiniteClosure fc);
	public Optional<Set<UnifyPair>> reduceFunNFi(UnifyPair pair, IFiniteClosure fc);
	
	/**
	 * Checks whether the erase1-Rule applies to the pair.
	 * @return True if the pair is erasable, false otherwise.
	 */
	public boolean erase1(UnifyPair pair, IFiniteClosure fc);
	
	/**
	 * Checks whether the erase2-Rule applies to the pair.
	 * @return True if the pair is erasable, false otherwise.
	 */
	public boolean erase2(UnifyPair pair, IFiniteClosure fc);
	
	/**
	 * Checks whether the erase3-Rule applies to the pair.
	 * @return True if the pair is erasable, false otherwise.
	 */
	public boolean erase3(UnifyPair pair);
	
	public Optional<UnifyPair> swap(UnifyPair pair);
	
	public Optional<UnifyPair> adapt(UnifyPair pair, IFiniteClosure fc);
	public Optional<UnifyPair> adaptExt(UnifyPair pair, IFiniteClosure fc);
	public Optional<UnifyPair> adaptSup(UnifyPair pair, IFiniteClosure fc);
	
	/**
	 * Applies the subst-Rule to a set of pairs (usually Eq').
	 * @param pairs The set of pairs where the subst rule should apply.
	 * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions.
	 */
	public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs, List<Set<Constraint<UnifyPair>>> oderConstraints);
	
	/**
	 * Applies the subst-Rule to a set of pairs (usually Eq').
	 * @param pairs The set of pairs where the subst rule should apply.
	 * @return An optional of the modified set, if there were any substitutions. An empty optional if there were no substitutions.
	 */
	public Optional<Set<UnifyPair>> subst(Set<UnifyPair> pairs);
	
}
