package com.hammurapi.extract;

import java.util.concurrent.TimeUnit;


public class NotEqual<T, V, C> extends ComparisonPredicate<T, V, C> {

	private boolean identity;

	public NotEqual(
			double initialCost, 
			TimeUnit costUnit,
			Extractor<T, V, C> leftExtractor, 
			Extractor<T, V, C> rightExtractor, 
			boolean identity) {
		super(initialCost, costUnit, leftExtractor, rightExtractor);
		this.identity = identity;
	}

	@Override
	@SuppressWarnings("unchecked")
	public com.hammurapi.extract.ComparisonResult compareTo(Extractor<T, Boolean, C> otherPredicate) {		
		if (otherPredicate instanceof Equal) {
			Equal<T, V, C> op = (Equal<T, V, C>) otherPredicate;			
			return (operandsAreEqual(op) || operandsAreReverseEqual(op)) ? ComparisonResult.OPPOSITE_NM: ComparisonResult.NOT_EQUAL_NM;
		} else if (equals(otherPredicate) || (otherPredicate instanceof NotEqual && operandsAreReverseEqual((NotEqual) otherPredicate))) {
			return ComparisonResult.EQUAL_NM;
		} else if (otherPredicate instanceof Not) {
			Not<T, C> op = (Not<T, C>) otherPredicate;
			ComparisonResult cr = compareTo(op.getPredicate());
			if (cr.isOneToOneMapping()) {
				switch (cr.getType()) {
				case EQUAL:
					return ComparisonResult.EQUAL_NM;
				case OPPOSITE:
					return ComparisonResult.OPPOSITE_NM;
				default:
					return ComparisonResult.NOT_EQUAL_NM;
				}
			}
		}
		/**
		 * TODO Implement comparisons.
		 * a * b ? c * d, * - can be <, <=, ==, !=, =>, >
		 * 36 permutations. Each permutation - compare a/b, c/d 
		 */
		
		return super.compareTo(otherPredicate);
	}

	@Override
	protected boolean compare(int n1, int n2) {
		return n1!=n2;
	}
	
	@Override
	protected boolean compare(Object o1, Object o2) {
		if (identity) {
			return o1!=o2;
		}
		
		if (o1==null) {
			return o2!=null;
		}

		return !o1.equals(o2);
	}

	@Override
	protected boolean compare(long n1, long n2) {
		return n1!=n2;
	}

	@Override
	protected boolean compare(float n1, float n2) {
		return n1!=n2;
	}

	@Override
	protected boolean compare(double n1, double n2) {
		return n1!=n2;
	}

	@Override
	protected Extractor<T, Boolean, C> newInstance(Extractor<T, V, C> leftExtractor, Extractor<T, V, C> rightExtractor) {
		return new NotEqual<T,V,C>(initialCost, costUnit, leftExtractor, rightExtractor, identity);
	}
	
	public boolean isIdentity() {
		return identity;
	}
}
