/***********************************************************************

GECCO, a platform for command and control gaming

Copyright (C) 2001 Henrik Bäärnhielm, Andreas Enblom, Niklas
Hallenfur, Karl Hasselström, Henrik Hägerström, Oskar Linde, Jing Fu
Zi and Jon Åslund

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

***********************************************************************/

package gecco.server.automaton;
import gecco.server.core.*;

import java.awt.Color;

/**
 *  The superclass for the automaton used in a game. This class should be
 *  subclassed by every game implementation. For each point on the map, one
 *  instance of this class is instanciated. Concrete subclasses should implement
 *  all states of the automaton and the different events that should be sent
 *  from or to the automaton. In particular, the subclasses should determine
 *  what colour the automaton should have, because that will be the colour of
 *  that pixel on the map. It is to subclass this class that the game designer
 *  can make the map dynamic in many ways, for example to let a fire spread
 *  across the map.
 *
 * @author     Henrik Bäärnhielm, Karl Hasselström, Henrik Hägerström
 * @created    April 23, 2001
 */
public abstract class Automaton {

    /**
     *  The current color which is to be sent to the client in a given state.
     */
    protected Color currentColor;

    /**
     *  Flag to indicate if the state of the automaton has changed.
     */
    private boolean changed = false;

    /**
     *  The current state of the automaton.
     */
    private int currentState;


    /**
     *  Constructor for the Automaton object
     */
    public Automaton() {
    }


    /**
     *  Sets the current color for the automaton.
     *
     * @param  r  The red component of the new color.
     * @param  g  The gree component of the new color.
     * @param  b  The blue component of the new color.
     */
    public void setCurrentColor(int r, int g, int b) {
        currentColor = new Color(r, g, b);
    }


    /**
     *  Gets the UnitEvent for the current state of the automaton. This method
     *  is called when a unit moves over the automaton.
     *
     * @param  unitType  The name of the UnitType of the unit that has moved
     *      over the automaton
     * @return           The UnitEvent for the current state. May be null if
     *      there is no event for this state.
     */
    public abstract UnitEvent getUnitEventForCurrentState(String unitType);


    /**
     *  Gets the CurrentColor attribute of the Automaton object
     *
     * @return    The CurrentColor value
     */
    public Color getCurrentColor() {
        return currentColor;
    }


    /**
     *  Gets the State attribute of the Automaton object
     *
     * @return    The State value
     */
    public int getState() {
        return currentState;
    }


    /**
     *  Initialises the automaton. Is only used by the game engine after the
     *  automaton has been dynamically loaded and instanciated.
     *
     * @param  initialState  Description of Parameter
     */
    public void initialize(int initialState) {
        setState(initialState);
    }


    /**
     *  The update method of the automaton. The states of the surronding
     *  automatons is provided in a 3x3 integer grid. The neighbour to the upper
     *  left is [0][0], the neighbour to the upper right is in [2][0].
     *
     * @param  neighbourStates  The states of the surrounding automatons, given
     *      in a 3x3 integer grid.
     * @return                  An AutomatonReturn object
     */
    public abstract AutomatonReturn update(int[][] neighbourStates);


    /**
     *  Handles incoming event to the automaton.
     *
     * @param  event  The AutomatonEvent
     * @return        An AutomatonReturn object
     */
    public abstract AutomatonReturn handleEvent(AutomatonEvent event);


    /**
     *  Indicates if the automaton has changed state since the last call to this
     *  method.
     *
     * @return    true if the state has been changed, false otherwise
     */
    public boolean hasChanged() {
        boolean b = changed;
        changed = false;
        return b;
    }


    /**
     *  Sets the State attribute of the Automaton object
     *
     * @param  newState  The new State value
     */
    protected void setState(int newState) {
        if (newState != currentState) {
            changed = true;
            currentState = newState;
        }
    }

}


