/* Rules */
import com.google.common.base.Function;
import com.google.common.base.Predicate;

import java.util.Collection;
import java.util.LinkedList;

/**
 * @author ymeymann@gmail.com
 * @since Oct 30, 2007 11:53:10 PM
 */
public class Rules<F,T> extends LinkedList<Rules.Rule<F,T>> implements Function<F,T> {
  private Function<? super F, ? extends T> defaultFunction = null;

   public Rules() {
     super();
   }

  public Rules(Collection<? extends Rules.Rule<F,T>> c) {
    super(c);
  }

  public Rules<F,T> addRule(Predicate<? super F> condition, Function<? super F, ? extends T> action) {
    add(new Rule<F,T>(condition, action));
    return this;
  }

  public Function<? super F, ? extends T> getDefault() {
    return defaultFunction;
  }

  public Rules<F,T> setDefault(Function<? super F, ? extends T> defaultFunction) {
    this.defaultFunction = defaultFunction;
    return this;
  }

  public Rules<F,T> noDefault() {
    setDefault(null);
    return this;
  }

  public T apply(F from) {
    for (Rule<F,T> rule: this) {
      if (rule.getPredicate().apply(from)) return rule.getFunction().apply(from);
    }
    Function<? super F, ? extends T> def = getDefault();
    return def != null ? def.apply(from) : null;
  }

  public static final class Rule<A,B> {
    private final Predicate<? super A> predicate;
    private final Function<? super A, ? extends B> function;

    public Rule(Predicate<? super A> predicate, Function<? super A, ? extends B> function) {
      this.predicate = predicate;
      this.function = function;
    }

    public Predicate<? super A> getPredicate() {
      return predicate;
    }

    public Function<? super A, ? extends B> getFunction() {
      return function;
    }
  }


}