package com.hammurapi.extract;

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * This predicate evaluates to true for <code>timeInterval</code> after construction. 
 * Then it evaluates to false.
 * @author Pavel Vlasov
 *
 * @param <T>
 * @param <C>
 */
public class TimeIntervalPredicate<T,C> implements Predicate<T,C> {
	
	private boolean nanos;
	long end;
	
	public TimeIntervalPredicate(TimeUnit timeUnit, long interval) {
		nanos = TimeUnit.MILLISECONDS.compareTo(timeUnit)>0;
		long start = nanos ? System.nanoTime() : System.currentTimeMillis();
		end = start + (nanos ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS).convert(interval, timeUnit);		
	}

	@Override
	public Boolean extract(
			C context,
			Map<C, Map<Extractor<T, ? super Boolean, C>, ? super Boolean>> cache,
			T... obj) {
		return (nanos ? System.nanoTime() : System.currentTimeMillis()) < end;
	}

	@Override
	public Set<Integer> parameterIndices() {
		return Collections.emptySet();
	}

	@Override
	public boolean isContextDependent() {
		return false;
	}

	@Override
	public ComparisonResult compareTo(Extractor<T, Boolean, C> other) {
		if (equals(other)) {
			return ComparisonResult.EQUAL_NM;
		}
		return ComparisonResult.NOT_EQUAL_NM;
	}

	@Override
	public double getCost() {
		return 0;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (end ^ (end >>> 32));
		result = prime * result + (nanos ? 1231 : 1237);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		TimeIntervalPredicate other = (TimeIntervalPredicate) obj;
		if (end != other.end)
			return false;
		if (nanos != other.nanos)
			return false;
		return true;
	}
		
}
