package at.oefai.aaa.agent.jam;

import java.io.Serializable;
import java.util.ListIterator;

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

/**
 * A boolean-evaluable World Model retrieval.
 * @author Marc Huber
 * @author Jaeho Lee
 */
class RetrieveCondition extends RelationCondition implements Serializable {

    /** Constructor w/ World Model relation to retrieve and interpreter as arguments. */
    RetrieveCondition(final Relation pRelation, final WorldModelTable pWorldModel) {
        super(pRelation, pWorldModel);
    }

    // Member functions

    /** Compare the relation against the world model and add and/or delete bindings as appropriate. */
    public boolean check(DList<Binding> bindinglist) {
        ListIterator<Binding> ble = bindinglist.listIterator(); // needed for .previous() and .remove()
        while (ble.hasNext()) {
            Binding oldBinding = ble.next();

            Binding backupBinding = ble.previous();
            assert (backupBinding == oldBinding);
            // unbind variables before matching (difference from FACT condition)
            oldBinding.unbindVariables(getRelation().getArgs());

            Binding newBinding = new Binding(oldBinding);

            DList<Binding> bindList = getWorldModel().getWMBindingList(newBinding,getRelation(),false);
            for (Binding b : bindList) {
                ble.add(b);
            }
            // Stefan Rank: remove the oldBinding using the iterator
            backupBinding = ble.next();
            assert (backupBinding == oldBinding);
            ble.remove();
        }

        return (bindinglist.size() > 0);
    }

    /** Confirm whether the binding is valid against the current World Model. */
    public boolean confirm(Binding b) {
        b.unbindVariables(getRelation().getArgs());
        // now try match to get new values
        return getWorldModel().match(getRelation(), b);
    }

}

