//
// SMARTS cognitive science programming project
//

/**
 * The nervous system of a <code>Critter</code> which decides what to do on each step.
 * Its <code>step()</code> is called for each <code>Critter</code> whenever the "step"
 * button is clicked and is called multiple times when the play button is clicked.
 * The <code>Brain</code> can access the <code>Critter</code>'s <code>Sensor</code>
 * and <code>Effector</code> but not the <code>Critter</code> itself.
 */
public class Brain {
    
    /**
     * The <code>UI</code> object, needed so that messages can get written
     * to the <code>MessageFrame</code>.
     */
    private UI ui;

    /**
     * The <code>Sensor</code> responsible for getting information from the world.
     */
    private Sensor sensor;

    /**
     * The <code>Effector</code> responsible for attempting actions in the world.
     */
    private Effector effector;

    /**
     * The <code>int</code> associated with the <code>Critter</code>.
     */
    private int index;

    /**
     * A short-term memory that keeps track of the last four textures.
     */
    private int[] stm = {-1, -1, -1, -1};

    /**
     * Just assigns the three instance variables.
     * @param ui  The user interface for the program.
     * @param sensor  The <code>Sensor</code> for this <code>Critter</code>.
     * @param effector  The <code>Effector</code> for this <code>Critter</code>.
     * @param index    The int ID associated with the <code>Critter</code>, needed
     *    only so the <code>Brain</code> can identify itself.
     */
    public Brain(UI ui, Sensor sensor, Effector effector, int index) {
        this.ui = ui;
        this.sensor = sensor;
        this.effector = effector;
        this.index = index;
    }

    /**
     * A <code>String</code> representation of the <code>Brain</code>.
     *
     * @return A <code>String</code> consisting of "brain" plus the index.
     */
    public String toString() {
        return "brain" + index;
    }

    /**
     * Prints out the brain's name followed by the contents of the stm.
     */
    private void printSTM() {
        String s = toString() + "'s STM: ";
        int i;
        for (i = 0; i < 4; i++)
            s += stm[i] + " ";

        effector.say(s);
    }

    /**
     Updates the stm so that the new texture appears in the first (0) position
     and all of the other textures move down.
     @param texture  The new texture
    */ 
    private void updateSTM(int texture) {
        int i;
        // Move the first three textures to the next position, starting
        // with the third one and moving back
        for (i = 2; i >= 0; i--)
            stm[i + 1] = stm[i];
        // Put the next texture in the first position
        stm[0] = texture;
    }

    /**
     * Gets called for this critter
     * once whenever the "step" button is clicked and multiple times
     * whenever the "run" button is clicked.
     */
    public void step() {
        int texture = sensor.getTexture();
        updateSTM(texture);
        printSTM();
        if (texture == Sensor.SOFT)
            effector.eat();
        else if (texture == Sensor.EMPTY)
            effector.move();
        else
            effector.turn(1 + Utils.getRandomInt(5));
    }

} // class Brain

