package at.oefai.aaa.agent.jam;

import java.io.Serializable;

import at.oefai.aaa.agent.jam.types.Binding;

/**
 * Represents a plan ready to be intended for a goal in an agent's Applicable Plans List (APL).
 * @author Marc Huber
 * @author Jaeho Lee
 */
public class APLElement implements Serializable {

    private final Plan plan;
    private final Goal fromGoal;
    private final Binding binding;

    /** shallow copy constructor. */
    APLElement(final APLElement ae) {
        this.plan = ae.getPlan();
        this.fromGoal = ae.getFromGoal();
        this.binding = ae.getBinding();
    }

    /** standard constructor. */
    APLElement(final Plan p, final Goal g, final Binding b) {
        this.plan = p;
        this.fromGoal = g;
        this.binding = b;
    }


    // Member functions

    public final Plan getPlan() { return this.plan; }

    public final Goal getFromGoal() { return this.fromGoal; }

    public final Binding getBinding() { return this.binding; }

    /** Determine the instantiated plan's utility (defined currently as goal utility + plan utility). */
    public final float evalUtility() {
        // Note that goal utility uses its own internal binding and
        // the plan uses the APLElement binding
        final float goalUtility = (this.fromGoal != null) ? this.fromGoal.evalUtility() : 0f;
        final float planUtility = this.plan.evalUtility(this.binding);
        // Default to simple addition at this point.
        return goalUtility + planUtility;
    }


    /** Display information about the applicable plan. */
    public final String verboseString() {
        StringBuffer sb = new StringBuffer();
        sb.append("APLElement:" + "\n");
        sb.append("  From goal: " + this.fromGoal + "\n");
        sb.append("  Goal name: " + ((this.fromGoal != null) ? this.fromGoal.getName() : "none") + "\n");
        sb.append("  Plan name: " + this.plan.getName() + "\n");
        sb.append("  Utility: " + this.plan.evalUtility(this.binding) + "\n");
        sb.append(this.binding.formattedString() + "\n"); // SP (not removed, only less verbose --StefanRank)
        sb.append("\n");
        return sb.toString();
    }

    /** Display information about the applicable plan inline. */
    public final String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("APLElement:");
        sb.append(" Goal: " + this.fromGoal);
        sb.append(" Plan: " + this.plan.getName());
        sb.append(" Utility: " + this.plan.evalUtility(this.binding));
        return sb.toString();
    }

}

