package com.googlecode.prolog_cafe.lang;

import com.googlecode.prolog_cafe.exceptions.InternalException;

/**
 * Compound term. <br>
 * The <code>StructureTerm</code> class represents a compound term but list.<br>
 *
 * <pre>
 *  % father(abraham, X)
 *  Term a1 = SymbolTerm.makeSymbol("abraham");
 *  Term a2 = new VariableTerm();
 *  Term[] a3 = {a1, a2};
 *  Term a4 = SymbolTerm.makeSymbol("father", 2);
 *  Term  t = new StructureTerm(a4, a3);
 *  
 *  Term functor = ((StructureTerm)t).functor();
 *  Term[]  args = ((StructureTerm)t).args();
 *  int    arity = ((StructureTerm)t).arity();
 * </pre>
 *
 * @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
 * @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
 * @version 1.0
 */
public class StructureTerm extends Term {
    /** Holds the functor symbol of this <code>StructureTerm</code>. */
    protected SymbolTerm functor;

    /** Holds the argument terms of this <code>StructureTerm</code>. */
    protected Term[] args;

    /**
     * Constructs a new Prolog compound term
     * such that <code>name</code> is the functor symbol, and
     * <code>args</code> is the argument terms respectively.
     */
    public StructureTerm(String name, Term... args){
	this(SymbolTerm.create(name, args.length), args);
    }

    /**
     * Constructs a new Prolog compound term
     * such that <code>_functor</code> is the functor symbol, and 
     * <code>_args</code> is the argument terms respectively.
     */
    public StructureTerm(SymbolTerm _functor, Term... _args){
	if (_functor.arity() != _args.length)
	    throw new InternalException("Invalid argument length in StructureTerm");
	functor = _functor;
	args = _args;
    }

    /** Returns the functor symbol of this <code>StructureTerm</code>.
     * @return the value of <code>functor</code>.
     * @see #functor
     */
    public SymbolTerm functor(){ return functor; }

    /** Returns the arity of this <code>StructureTerm</code>.
     * @return the value of <code>arity</code>.
     * @see #arity
     */
    public int arity(){ return args.length; }

    /** Returns the argument terms of this <code>StructureTerm</code>.
     * @return the value of <code>args</code>.
     * @see #args
     */
    public Term[] args(){ return args; }

    /** Returns the string representation of functor symbol of this <code>StructureTerm</code>.
     * @return a <code>String</code> whose value is <code>functor.name()</code>.
     * @see #functor
     * @see SymbolTerm#name
     */
    public String name(){ return functor.name(); }

    public Term arg(int nth) { return args[nth]; }

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

    public boolean unify(Term t, Trail trail) {
	t = t.dereference();
	if (t instanceof VariableTerm) {
	    ((VariableTerm) t).bind(this, trail);
	    return true;
	}
	if (! (t instanceof StructureTerm))
	    return false;
	if (! functor.equals(((StructureTerm)t).functor()))
	    return false;
	for (int i=0; i<args.length; i++) {
	    if (! args[i].unify(((StructureTerm)t).args[i], trail))
		return false;
	}
	return true;
    }

    protected Term copy(Prolog engine) {
	Term[] a = new Term[args.length];
	for (int i=0; i<args.length; i++)
	    a[i] = args[i].copy(engine);
	return new StructureTerm(functor, a);
    }

    public boolean isGround() {
	for (int i=0; i<args.length; i++) {
	    if (! args[i].isGround())
		return false;
	}
	return true;
    }

    public String toQuotedString() {
	String delim = "";
	String s = functor.toQuotedString() + "(";
	for (int i=0; i<args.length; i++) {
	    s += delim + args[i].toQuotedString();
	    delim = ",";
	}
	s += ")";
	return s;
    }

    /* Object */
    /**
     * 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>StructureTerm</code>, has the same functor symbol and arity, and
     * all corresponding pairs of arguments in the two compound terms are <em>term-equal</em>.
     * @param obj the object to compare with. This must be dereferenced.
     * @return <code>true</code> if the given object represents a Prolog compound term
     * equivalent to this <code>StructureTerm</code>, false otherwise.
     * @see #compareTo
     */
    public boolean equals(Object obj) {
	if (! (obj instanceof StructureTerm))
	    return false;
	if (! functor.equals(((StructureTerm)obj).functor()))
	    return false;
	for (int i=0; i<args.length; i++) {
	    if (! args[i].equals(((StructureTerm)obj).args[i].dereference()))
		return false;
	}
	return true;
    }

    public int hashCode() {
	int h = 1;
	h = 31*h + functor.hashCode();
	for(int i=0; i<args.length; i++)
	    h = 31*h + args[i].dereference().hashCode();
	return h;
    }

    /** Returns a string representation of this <code>StructureTerm</code>. */
    public String toString() {
	String delim = "";
	String s = functor.toString() + "(";
	for (int i=0; i<args.length; i++) {
	    s += delim + args[i].toString();
	    delim = ",";
	}
	s += ")";
	return s;
    }

    /* 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>.
     */
    public int compareTo(Term anotherTerm) { // anotherTerm must be dereferenced.
	SymbolTerm functor2;
	Term[] args2;
	int arity2, rc;

	if (anotherTerm instanceof VariableTerm || ((anotherTerm instanceof IntegerTerm) || (anotherTerm instanceof DoubleTerm)) || anotherTerm instanceof SymbolTerm)
	    return AFTER;
	if (anotherTerm instanceof ListTerm) {
	    ListTerm t = (ListTerm)anotherTerm;
	    functor2 = ListTerm.SYM_DOT;
	    args2    = new Term[2];
	    args2[0] = t.car();
	    args2[1] = t.cdr();
	    arity2   = 2;
	} else if (anotherTerm instanceof StructureTerm) {
	    StructureTerm s = (StructureTerm)anotherTerm;
	    functor2 = s.functor();
	    args2    = s.args();
	    arity2   = s.arity();
	} else {
	    return BEFORE;
	}
	if (args.length != arity2)
	    return (args.length - arity2);
	if (! functor.equals(functor2))
	    return functor.compareTo(functor2);
	for (int i=0; i<args.length; i++) {
	    rc = args[i].compareTo(args2[i].dereference());
	    if (rc != EQUAL) 
		return rc;
	}
	return EQUAL;
    }
}
