package com.googlecode.prolog_cafe.lang;

import com.googlecode.prolog_cafe.exceptions.EvaluationException;
import com.googlecode.prolog_cafe.exceptions.IllegalTypeException;

/**
 * Integer.<br>
 * The class <code>IntegerTerm</code> wraps a value of primitive type 
 * <code>int</code>. 
 * <pre>
 *   Term t = new IntegerTerm(100);
 *   int i = ((IntegerTerm)t).intValue();
 * </pre>
 *
 * @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
 * @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
 * @version 1.0
 */
public class IntegerTerm extends NumberTerm {
    /** Holds an <code>int</code> value that this <code>IntegerTerm</code> represents. */
    protected int val;

    /** Constructs a new Prolog integer that represents the specified <code>int</code> value. */
    public IntegerTerm(int i) {	val = i; }

    /**
     * Returns the value of <code>val</code>.
     * @see #val
     */
    public int value() { return val; }

    @Override
    public int type() {
      return TYPE_INTEGER;
    }

    /* Term */
    @Override
    public boolean unify(Term t, Trail trail) {
	if (t instanceof VariableTerm)
	    return ((VariableTerm)t).unify(this, trail);
	if (! (t instanceof IntegerTerm))
	    return false;
	else 
	    return this.val == ((IntegerTerm)t).value();
    }

    /** 
     * @return the <code>boolean</code> whose value is
     * <code>convertible(Integer.class, type)</code>.
     * @see Term#convertible(Class, Class)
     */
    @Override
    public boolean convertible(Class<?> type) { return convertible(Integer.class, type); }

    @Override
    public String name() { return ""; }

    /** 
     * Returns a <code>java.lang.Integer</code> corresponds to this <code>IntegerTerm</code>
     * according to <em>Prolog Cafe interoperability with Java</em>.
     * @return a <code>java.lang.Integer</code> object equivalent to
     * this <code>IntegerTerm</code>.
     */
    @Override
    public Object toJava() { return Integer.valueOf(val); }

    /* Object */
    /** Returns a string representation of this <code>IntegerTerm</code>. */
    @Override
    public String toString() { return Integer.toString(this.val); }

    /**
     * Checks <em>term equality</em> of two terms.
     * The result is <code>true</code> if and only if the argument is an instance of
     * <code>IntegerTerm</code> and has the same <code>int</code> value as this object.
     * @param obj the object to compare with. This must be dereferenced.
     * @return <code>true</code> if the given object represents a Prolog integer 
     * equivalent to this <code>IntegerTerm</code>, false otherwise.
     * @see #compareTo
    */
    @Override
    public boolean equals(Object obj) {
	if (! (obj instanceof IntegerTerm))
	    return false;
	return this.val == ((IntegerTerm)obj).value();
    }

    @Override
    public int hashCode() { return this.val; }

    /* Comparable */
    /** 
     * Compares two terms in <em>Prolog standard order of terms</em>.<br>
     * It is noted that <code>t1.compareTo(t2) == 0</code> has the same
     * <code>boolean</code> value as <code>t1.equals(t2)</code>.
     * @param anotherTerm the term to compared with. It must be dereferenced.
     * @return the value <code>0</code> if two terms are identical; 
     * a value less than <code>0</code> if this term is <em>before</em> the <code>anotherTerm</code>;
     * and a value greater than <code>0</code> if this term is <em>after</em> the <code>anotherTerm</code>.
     */
    @Override
    public int compareTo(Term anotherTerm) { // anotherTerm must be dereferenced.
	if (anotherTerm instanceof VariableTerm || anotherTerm instanceof DoubleTerm)
	    return AFTER;
	if (! (anotherTerm instanceof IntegerTerm))
	    return BEFORE;
	int v = ((IntegerTerm)anotherTerm).value();
	if (this.val == v)
	    return EQUAL;
	if (this.val > v)
	    return AFTER;
	return BEFORE;
    }

    /* NumberTerm */
    @Override
    public int intValue() { return this.val; }

    @Override
    public long longValue() { return (this.val); }

    @Override
    public double doubleValue() { return (this.val); }

    @Override
    public int arithCompareTo(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    return - (t.arithCompareTo(this));
	int v = t.intValue();
	if (this.val == v)
	    return EQUAL;
	if (this.val > v)
	    return AFTER;
	return BEFORE;
    }

    @Override
    public NumberTerm abs() { return new IntegerTerm(Math.abs(this.val)); }

    @Override
    public NumberTerm acos() { return new DoubleTerm(Math.acos(this.doubleValue())); }

    @Override
    public NumberTerm add(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    return t.add(this);
	return new IntegerTerm(this.val + t.intValue());
    }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     */
    @Override
    public NumberTerm and(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	return new IntegerTerm(this.val & t.intValue());
    }

    @Override
    public NumberTerm asin() { return new DoubleTerm(Math.asin(this.doubleValue())); }

    @Override
    public NumberTerm atan() { return new DoubleTerm(Math.atan(this.doubleValue())); }

    @Override
    public NumberTerm ceil() { return this; }

    @Override
    public NumberTerm cos() { return new DoubleTerm(Math.cos(this.doubleValue())); }

    /** 
     * @exception EvaluationException if the given argument
     * <code>NumberTerm</code> represents <coe>0</code>.
     */
    @Override
    public NumberTerm divide(NumberTerm t) { 
	if (t.doubleValue() == 0)
	    throw new EvaluationException("zero_divisor");
	return new DoubleTerm(this.doubleValue() / t.doubleValue()); 
    }

    @Override
    public NumberTerm exp() { return new DoubleTerm(Math.exp(this.doubleValue())); }

    @Override
    public NumberTerm floatIntPart() { throw new IllegalTypeException("float", this); }

    @Override
    public NumberTerm floatFractPart() { throw new IllegalTypeException("float", this); }

    @Override
    public NumberTerm floor() { return this; }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     * @exception EvaluationException if the given argument
     * <code>NumberTerm</code> represents <coe>0</code>.
     */
    @Override
    public NumberTerm intDivide(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	if (t.intValue() == 0)
	    throw new EvaluationException("zero_divisor");
	return new IntegerTerm(this.val / t.intValue());
    }

    /** 
     * @exception EvaluationException if this object represents <coe>0</code>.
     */
    @Override
    public NumberTerm log() { 
	if (this.val == 0)
	    throw new EvaluationException("undefined");
	return new DoubleTerm(Math.log(this.doubleValue())); 
    }

    @Override
    public NumberTerm max(NumberTerm t) {
	if (t instanceof DoubleTerm) 
	    return t.max(this);
	return new IntegerTerm(Math.max(this.val, t.intValue()));
    }

    @Override
    public NumberTerm min(NumberTerm t) {
	if (t instanceof DoubleTerm) 
	    return t.min(this);
	return new IntegerTerm(Math.min(this.val, t.intValue()));
    }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     * @exception EvaluationException if the given argument
     * <code>NumberTerm</code> represents <coe>0</code>.
     */
    @Override
    public NumberTerm mod(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	if (t.intValue() == 0)
	    throw new EvaluationException("zero_divisor");
	return new IntegerTerm(this.val % t.intValue());
    }

    @Override
    public NumberTerm multiply(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    return t.multiply(this);
	return new IntegerTerm(this.val * t.intValue());
    }

    @Override
    public NumberTerm negate() { return new IntegerTerm(- this.val); }

    @Override
    public NumberTerm not() { return new IntegerTerm(~ this.val); }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     */
    @Override
    public NumberTerm or(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	return new IntegerTerm(this.val | t.intValue());
    }

    @Override
    public NumberTerm pow(NumberTerm t) { return new DoubleTerm(Math.pow(this.doubleValue(), t.doubleValue())); }

    @Override
    public NumberTerm rint() { return new DoubleTerm(this.doubleValue()); }

    @Override
    public NumberTerm round() { return this; }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     */
    @Override
    public NumberTerm shiftLeft(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	return new IntegerTerm(this.val << t.intValue());
    }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     */
    @Override
    public NumberTerm shiftRight(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	return new IntegerTerm(this.val >> t.intValue());
    }

    @Override
    public NumberTerm signum() {return new IntegerTerm((int) Math.signum((double) this.val)); }

    @Override
    public NumberTerm sin() { return new DoubleTerm(Math.sin(this.doubleValue())); }

    /** 
     * @exception EvaluationException if this object represents
     * an integer less than <coe>0</code>.
     */
    @Override
    public NumberTerm sqrt() { 
	if (this.val < 0)
	    throw new EvaluationException("undefined");
	return new DoubleTerm(Math.sqrt(this.doubleValue())); 
    }

    @Override
    public NumberTerm subtract(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    return new DoubleTerm(this.doubleValue() - t.doubleValue());
	return new IntegerTerm(this.val - t.intValue());
    }

    @Override
    public NumberTerm tan() { return new DoubleTerm(Math.tan(this.doubleValue())); }

    @Override
    public NumberTerm toDegrees() { return new DoubleTerm(Math.toDegrees(this.doubleValue())); }

    @Override
    public NumberTerm toFloat() { return new DoubleTerm(this.val); }

    @Override
    public NumberTerm toRadians() { return new DoubleTerm(Math.toRadians(this.doubleValue())); }

    @Override
    public NumberTerm truncate() { return this; }

    /** 
     * @exception IllegalTypeException if the given argument
     * <code>NumberTerm</code> is a floating point number.
     */
    @Override
    public NumberTerm xor(NumberTerm t) {
	if (t instanceof DoubleTerm)
	    throw new IllegalTypeException("integer", t);
	return new IntegerTerm(this.val ^ t.intValue());
    }
}
