package at.oefai.aaa.agent.jam;


/**
 * Represents one match found between a perception and the standards of the agent.
 * @author Stefan Rank
 */
abstract class ActionAppraisal extends AbstractFactAppraisal {

    // conformance to standards (praiseworthy if >0 or blameworthy if <0):
    private float conformance = 0;

    ActionAppraisal(final float pConformanceValue, final WorldModelRelation pRelation,
                    final Interpreter pInterpreter) {
        super(pRelation, pInterpreter);
        this.setConformance(pConformanceValue);
        // if new post an immediate emotion goal (impulse) with high 'utility' if emotional enough
        this.postImpulse();
        this.infoProcessingEffects(pInterpreter.getWorldModel());
        this.tryToCope();
    }

    public static ActionAppraisal newActionAppraisal(final float pConformanceValue, final WorldModelRelation pRelation,
            final Interpreter pInterpreter) {
        if (pRelation.getResponsible().equals(pInterpreter.getName())) { // self-initiated
            if (pConformanceValue > 0) { // praiseworthy
                return new ActionPrideAppraisal(pConformanceValue, pRelation, pInterpreter);
            } else if (pConformanceValue < 0) { // blameworthy
                return new ActionShameAppraisal(pConformanceValue, pRelation, pInterpreter);
            }
        } else { // other-initiated
            if (pConformanceValue > 0) { // praiseworthy
                return new ActionAdmireAppraisal(pConformanceValue, pRelation, pInterpreter);
            } else if (pConformanceValue < 0) { // blameworthy
                return new ActionAngerAppraisal(pConformanceValue, pRelation, pInterpreter);
            }
        }
        assert false : "strange stuff happening when factoring an ActionAppraisal";
        return null;
    }

    private void setConformance(final float pConformanceValue) {
        this.conformance = pConformanceValue;
    }

    public void update(final float conformanceValue) {
        this.setConformance(conformanceValue);
    }

    public float getIntensity() {
        return super.getIntensity() * Math.abs(this.conformance);
    }

    // SP
    public float getSignedIntensity() {
        return super.getIntensity() * this.conformance;
    }

    protected abstract float getPreferenceChange();

    public final void infoProcessingEffects(final WorldModelTable pWorldModel) {
        // change the preference for the responsible one
        String responsible = this.getRelation().getResponsible();
        pWorldModel.changePreference(responsible, getPreferenceChange());
    }

    protected StringBuffer valuesString() {
        return super.valuesString().append(" conformance: " + this.conformance);
    }

}
