package com.hammurapi.extract;

import java.util.Map;
import java.util.Set;

import com.hammurapi.extract.ComparisonResult.Type;

public class Not<T, C> implements Predicate<T, C>, FacadeExtractor<T, Boolean, C> {
	
	private Predicate<T, C> predicate;

	public Not(Predicate<T, C> predicate) {
		this.predicate = predicate;
	}

	public ComparisonResult compareTo(Extractor<T, Boolean, C> otherPredicate) {
		ComparisonResult cr = predicate.compareTo(otherPredicate);
		switch (cr.getType()) {
		case EQUAL: 
			return new ComparisonResult(Type.OPPOSITE, cr.getIndexMap());
		case LESS_RESTRICTIVE:
			return new ComparisonResult(Type.OPPOSITE_LESS_RESTRICTIVE, cr.getIndexMap());
		case MORE_RESTRICTIVE:
			return new ComparisonResult(Type.OPPOSITE_MORE_RESTRICTIVE, cr.getIndexMap());
		case NOT_EQUAL:
			return new ComparisonResult(Type.NOT_EQUAL, cr.getIndexMap());
		case OPPOSITE:
			return new ComparisonResult(Type.EQUAL, cr.getIndexMap());
		case OPPOSITE_LESS_RESTRICTIVE:
			return new ComparisonResult(Type.LESS_RESTRICTIVE, cr.getIndexMap());
		case OPPOSITE_MORE_RESTRICTIVE:
			return new ComparisonResult(Type.MORE_RESTRICTIVE, cr.getIndexMap());
		default :
			throw new ExtractorException("Invalid comparison result");
		}
	}

	public Predicate<T, C> getPredicate() {
		return predicate;
	}

	public Boolean extract(
			C context,
			Map<C, Map<Extractor<T, ? super Boolean, C>, ? super Boolean>> cache,
			T... obj) {
		return !predicate.extract(context, cache, obj);
	}

	public Set<Integer> parameterIndices() {
		return predicate.parameterIndices();
	}


	public boolean isContextDependent() {
		return predicate.isContextDependent();
	}	
	
	@Override
	public double getCost() {
		return predicate.getCost();
	}

}
