package com.googlecode.prolog_cafe.lang;

import static com.googlecode.prolog_cafe.lang.PredicateEncoder.encode;
import java.lang.reflect.Constructor;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Prolog class loader.
 *
 * @author Mutsunori Banbara (banbara@kobe-u.ac.jp)
 * @author Naoyuki Tamura (tamura@kobe-u.ac.jp)
 * @version 1.1
 */
public class PrologClassLoader extends ClassLoader {
  private final ConcurrentHashMap<Key, CacheEntry> predicateCache =
      new ConcurrentHashMap<Key, CacheEntry>();

  /** Initialize using the {@link ClassLoader#getSystemClassLoader()}. */
  public PrologClassLoader() {
  }

  /**
   * Initialize using a specific parent ClassLoader.
   *
   * @param parent source for all predicates in this context.
   */
  public PrologClassLoader(ClassLoader parent) {
    super(parent);
  }

  /**
   * Check whether the predicate class for the given arguments is defined.
   *
   * @param pkg package name
   * @param functor predicate name
   * @param arity predicate arity
   * @return <code>true</code> if the predicate <code>pkg:functor/arity</code>
   *         is defined, otherwise <code>false</code>.
   */
  public boolean definedPredicate(String pkg, String functor, int arity) {
    try {
      return findPredicate(pkg, functor, arity) instanceof ValidPredicate;
    } catch (ClassNotFoundException cnfe) {
      return false;
    }
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Term... args) {
    return predicate(pkg, functor, Success.SUCCESS, args);
  }

  /**
   * Allocate a predicate and configure it with the specified arguments.
   *
   * @param pkg package the predicate is in.
   * @param functor name of the predicate.
   * @param cont operation to execute if the predicate is successful. Usually
   *        this is {@link Success#SUCCESS}.
   * @param args arguments to pass. The arity is derived from the arguments.
   * @return the predicate encapsulating the logic and the arguments.
   */
  public Predicate predicate(String pkg, String functor, Operation cont, Term... args) {
    int arity = args.length;
    try {
      CacheEntry ent = findPredicate(pkg, functor, arity);
      if (ent instanceof ValidPredicate) {
        Object[] a = new Object[arity + 1];
        for (int i = 0; i < arity; i++)
          a[i] = args[i];
        a[arity] = cont;
        return ((ValidPredicate) ent).constructor.newInstance(a);
      }
    } catch (Exception cause) {
      ExistenceException err2 = new ExistenceException(
          "procedure",
          term(pkg, functor, arity),
          cause.toString());
      err2.initCause(cause);
      throw err2;
    }
    throw new ExistenceException("procedure", term(pkg, functor, arity), "NOT_FOUND");
  }

  private static StructureTerm term(String pkg, String functor, int arity) {
    return new StructureTerm(":",
      SymbolTerm.create(pkg),
      new StructureTerm("/",
        SymbolTerm.create(functor),
        new IntegerTerm(arity)));
  }

  private CacheEntry findPredicate(String pkg, String functor, int arity)
      throws ClassNotFoundException {
    Key key = new Key(pkg, functor, arity);
    CacheEntry entry = predicateCache.get(key);
    if (entry == null) {
      Class<?> clazz;
      try {
        clazz = Class.forName(
            encode(pkg, functor, arity),
            false /* avoid resolve */,
            this);
      } catch (ClassNotFoundException cnfe) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw cnfe;
      }

      if (!Predicate.class.isAssignableFrom(clazz)) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException(clazz.getName(),
          new ClassCastException("Does not extend " + Predicate.class));
      }

      Class[] params = new Class[arity + 1];
      for (int i = 0; i < arity; i++)
        params[i] = Term.class;
      params[arity] = Operation.class;

      Constructor<Predicate> cons;
      try {
        cons = (Constructor<Predicate>) clazz.getDeclaredConstructor(params);
      } catch (NoSuchMethodException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Wrong constructor on " + clazz.getName(), e);

      } catch (SecurityException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Constructor not visible " + clazz.getName(), e);
      }
      cons.setAccessible(true);

      try {
        Class.forName(clazz.getName(), true /* resolve now */, this);
      } catch (ClassNotFoundException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (RuntimeException e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);

      } catch (LinkageError e) {
        predicateCache.put(key, NotFound.INSTANCE);
        throw new ClassNotFoundException("Cannot initialize " + clazz.getName(), e);
      }

      entry = new ValidPredicate(cons);
      predicateCache.put(key, entry);
    }
    return entry;
  }

  private static final class Key {
    final String pkg;
    final String functor;
    final int arity;

    Key(String pkg, String functor, int arity) {
      this.pkg = pkg;
      this.functor = functor;
      this.arity = arity;
    }

    @Override
    public int hashCode() {
      int h = pkg.hashCode();
      h = (h * 31) + functor.hashCode();
      h = (h * 31) + arity;
      return h;
    }

    @Override
    public boolean equals(Object other) {
      if (other instanceof Key) {
        Key b = (Key) other;
        return arity == b.arity && pkg.equals(b.pkg) && functor.equals(b.functor);
      }
      return false;
    }
  }

  private static abstract class CacheEntry {
  }

  private static class NotFound extends CacheEntry {
    static final NotFound INSTANCE = new NotFound();
  }

  private static class ValidPredicate extends CacheEntry {
    final Constructor<Predicate> constructor;

    ValidPredicate(Constructor<Predicate> c) {
      constructor = c;
    }
  }
}
