package com.googlecode.prolog_cafe.lang;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;
/**
 * Atom.<br>
 * The <code>SymbolTerm</code> class represents a Prolog atom.<br>
 *
 * <pre>
 *   Term t = SymbolTerm.makeSymbol("kobe");
 *   String name = ((SymbolTerm)t).name();
 * </pre>
 *
 * @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
 * @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
 * @version 1.0
 */
public abstract class SymbolTerm extends Term {
    /** Symbol table. */
    private static final ConcurrentHashMap<Key, InternRef> SYMBOL_TABLE =
      new ConcurrentHashMap<Key, InternRef>();

    private static final ReferenceQueue<Interned> DEAD = new ReferenceQueue<Interned>();

    private static final class Key {
      final String name;
      final int arity;

      Key(String n, int a) {
        name = n;
        arity = a;
      }

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

      @Override
      public boolean equals(Object other) {
        Key k = (Key) other;
        return arity == k.arity && name.equals(k.name);
      }
    }

    private static final class InternRef extends WeakReference<Interned> {
      final Key key;

      InternRef(Key key, Interned sym) {
        super(sym, DEAD);
        this.key = key;
      }
    }

    private static final class Dynamic extends SymbolTerm {
      Dynamic(String name, int arity) {
        super(name, arity);
      }
    }

    private static final class Interned extends SymbolTerm {
      Interned(String name, int arity) {
        super(name, arity);
      }
    }

    private static final SymbolTerm colon2 = intern(":", 2);

    /** Returns a Prolog atom for the given character. */
    public static SymbolTerm create(char c) {
      if (0 <= c && c <= 127)
        return intern(Character.toString(c), 0);
      else
        return create(Character.toString(c));
    }

    /** Returns a Prolog atom for the given name. */
    public static SymbolTerm create(String _name) {
      return new Dynamic(_name, 0);
    }

    /** Returns a Prolog atom for the given name. */
    public static SymbolTerm create(String _name, int arity) {
      // For a non-zero arity try to reuse the term, its probable this is a
      // structure term and those are more commonly declared in code
      // to be a type of object the code manipulates, therefore also very
      // likely to already be in the cache.
      if (arity != 0)
        return softReuse(_name, arity);

      return new Dynamic(_name, 0);
    }

    /** Returns a Prolog functor for the given name and arity. */
    public static StructureTerm create(String pkg, String name, int arity) {
      // This is likely a specific function that exists in code, so try to reuse
      // the symbols that are involved in the term.
      return new StructureTerm(colon2, softReuse(pkg, 0), softReuse(name, arity));
    }

    /** Returns a Prolog atom for the given name. */
    public static SymbolTerm intern(String _name) {
      return intern(_name, 0);
    }

    /** Returns a Prolog functor for the given name and arity. */
    public static SymbolTerm intern(String _name, int _arity) {
      _name = _name.intern();
      Key key = new Key(_name, _arity);

      Reference<? extends Interned> ref = SYMBOL_TABLE.get(key);
      if (ref != null) {
        Interned sym = ref.get();
        if (sym != null)
          return sym;
        SYMBOL_TABLE.remove(key, ref);
        ref.enqueue();
      }

      gc();

      Interned sym = new Interned(_name, _arity);
      InternRef nref = new InternRef(key, sym);
      InternRef oref = SYMBOL_TABLE.putIfAbsent(key, nref);
      if (oref != null) {
        SymbolTerm osym = oref.get();
        if (osym != null)
          return osym;
      }
      return sym;
    }

    static void gc() {
      Reference<? extends Interned> ref;
      while ((ref = DEAD.poll()) != null) {
        SYMBOL_TABLE.remove(((InternRef) ref).key, ref);
      }
    }

    private static SymbolTerm softReuse(String _name, int _arity) {
      Key key = new Key(_name, _arity);
      Reference<? extends Interned> ref = SYMBOL_TABLE.get(key);
      if (ref != null) {
        Interned sym = ref.get();
        if (sym != null)
          return sym;
        SYMBOL_TABLE.remove(key, ref);
        ref.enqueue();
      }

      // If reuse wasn't possible, construct the term dynamically.
      return new Dynamic(_name, _arity);
    }

    /** Holds a string representation of this <code>SymbolTerm</code>. */
    protected final String name;

    /** Holds the arity of this <code>SymbolTerm</code>. */
    protected final int arity;

    /** Constructs a new Prolog atom (or functor) with the given symbol name and arity. */
    protected SymbolTerm(String _name, int _arity) {
	name  = _name;
	arity = _arity;
    }

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

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

    /* Term */
    public boolean unify(Term t, Trail trail) {
      t = t.dereference();
      if (t.isVariable()) {
        ((VariableTerm) t).bind(this, trail);
        return true;
      }
      return eq(this, t);
    }

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

    @Override
    public boolean equals(Object obj) {
      return obj instanceof Term && eq(this, (Term) obj);
    }

    private static boolean eq(SymbolTerm a, Term b0) {
      if (a == b0) {
        return true;
      } else if (b0 instanceof SymbolTerm && (a instanceof Dynamic || b0 instanceof Dynamic)) {
        SymbolTerm b = (SymbolTerm) b0;
        return a.arity == b.arity && a.name.equals(b.name);
      } else {
        return false;
      }
    }

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

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

    public String toQuotedString() { return Token.toQuotedString(name); }

    /** Returns a string representation of this <code>SymbolTerm</code>. */
    public String toString() { return name; }

    /* 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.
	if (anotherTerm.isVariable() || anotherTerm.isNumber())
	    return AFTER;
	if (! anotherTerm.isSymbol())
	    return BEFORE;
	if (this == anotherTerm)
	    return EQUAL;
	int x = name.compareTo(((SymbolTerm)anotherTerm).name());
	if (x != 0)
	    return x;
	int y = this.arity - ((SymbolTerm)anotherTerm).arity();
	if (y != 0)
	    return y;
	throw new InternalException("SymbolTerm is not unique");
    }
}
