package com.hammurapi.extract;

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

/**
 * Constants don't extract any data from sources, but may extract
 * data from context.
 * @author Pavel Vlasov.
 *
 * @param <V>
 * @param <C>
 */
public class Constant<T, V, C> extends ExtractorBase<T, V, C> {
	
	private V value;
	
	protected Constant() {
		super(0,null);
	}

	public V getValue() {
		return value;
	}

	public Constant(V value) {
		super(0,null);
		this.value = value;
	}

	protected V extractInternal(C context, Map<C, Map<Extractor<T, ? super V, C>, ? super V>> cache, T... obj) {
		return value;
	}

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

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((value == null) ? 0 : value.hashCode());
		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Constant other = (Constant) obj;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		return true;
	}

	public boolean isContextDependent() {
		return false;
	}
	
	@Override
	public String toString() {
		return getClass().getName()+"("+(value==null ? "null" : value + "["+value.getClass()+"]")+")";
	}
	
	@Override
	public ComparisonResult compareTo(Extractor<T, V, C> other) {
		if (other instanceof Constant) {
			Object otherValue = ((Constant) other).value;
			if (value==null) {
				return otherValue==null ? ComparisonResult.EQUAL_NM : ComparisonResult.UNEQUAL_NM; 
			}
			
			// TODO - Number promotion and comparison.
			
			return value.equals(otherValue) ? ComparisonResult.EQUAL_NM : value instanceof Boolean ? ComparisonResult.OPPOSITE_NM : ComparisonResult.UNEQUAL_NM;
		}
		return super.compareTo(other);
	}

}
