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

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.game.oresund;
import gecco.server.automaton.*;

import gecco.server.core.UnitEvent;
import java.util.*;

/**
 *  Description of the Class
 *
 */
public class AutomatonImpl extends Automaton {

    /**
     *  Description of the Field
     */
    final static String CITY_EVENT_STRING = "CITY";
    /**
     *  Description of the Field
     */
    final static String SURVIVOR_EVENT_STRING = "SURVIVOR";
    /**
     *  Description of the Field
     */
    final static String WATER_EVENT_STRING = "WATER";
    /**
     *  Description of the Field
     */
    final static String FOREST_EVENT_STRING = "FOREST";
    /**
     *  Description of the Field
     */
    final static String LAND_EVENT_STRING = "LAND";
    /**
     *  Description of the Field
     */
    final static String BRIDGE_EVENT_STRING = "BRIDGE";
    /**
     *  Description of the Field
     */
    final static int CITY = 1;
    /**
     *  Description of the Field
     */
    final static int SURVIVOR = 2;
    /**
     *  Description of the Field
     */
    final static int WATER = 3;
    /**
     *  Description of the Field
     */
    final static int FOREST = 4;
    /**
     *  Description of the Field
     */
    final static int LAND = 5;
    /**
     *  Description of the Field
     */
    final static int BRIDGE = 6;

    /**
     *  Description of the Field
     */
    final static HashMap stateToColour = new HashMap();


    /**
     *  Gets the UnitEventForCurrentState attribute of the AutomatonImpl object
     *
     * @param  unitType  Description of Parameter
     * @return           The UnitEventForCurrentState value
     */
    public UnitEvent getUnitEventForCurrentState(String unitType) {
        return null;
    }


    /**
     *  Description of the Method
     *
     * @param  initialState                  Description of Parameter
     * @exception  IllegalArgumentException  Description of Exception
     */
    public void initialize(int initialState) throws IllegalArgumentException {
        //System.out.println("AutomatonImpl instanciated!");
        if (!stateToColour.keySet().contains(new Integer(initialState))) {
            throw new IllegalArgumentException("Non-existent state");
        }

        setColour(initialState);

    }


    /**
     *  Description of the Method
     *
     * @param  neighbourStates  Description of Parameter
     * @return                  Description of the Returned Value
     */
    public AutomatonReturn update(int[][] neighbourStates) {

        switch (getState()) {
            case BRIDGE:
                if (Math.random() < 0.96) {
                    setColour(WATER);
                    return new AutomatonReturnQueueNeighbours(0.5);
                } else {
                    setColour(SURVIVOR);
                    return new AutomatonReturnQueueSelfAndNeighbours(100.0, 0.5);
                }

            case WATER:
                if (Math.random() < 0.1) {
                    if (existsNeighboursWithState(neighbourStates, SURVIVOR)) {
                        setColour(SURVIVOR);
                        return new AutomatonReturnQueueSelfAndNeighbours(100.0, 10.0);
                    }
                }
                break;
            case SURVIVOR:
                if (Math.random() < 0.2) {
                    setColour(WATER);

                } else {
                    return new AutomatonReturnQueueSelf(100.0);
                }
                break;
            default:
                break;
        }
        return new AutomatonReturnNoAction();
    }


    /**
     *  Description of the Method
     *
     * @param  event  Description of Parameter
     * @return        Description of the Returned Value
     */
    public AutomatonReturn handleEvent(AutomatonEvent event) {

        if (event.getEventName().equals("Crasch")) {
            setColour(WATER);
            return new AutomatonReturnQueueSelfAndNeighbours(1.0, 5.0);
        } else if (event.getEventName().equals("Rescue")) {
            if (getState() == SURVIVOR) {
                setColour(WATER);
            }
        }

        return new AutomatonReturnNoAction();
    }


    /**
     *  Sets the Colour attribute of the AutomatonImpl object
     *
     * @param  state                         The new Colour value
     * @exception  IllegalArgumentException  Description of Exception
     */
    private void setColour(int state) throws IllegalArgumentException {
        if (!stateToColour.keySet().contains(new Integer(state))) {
            throw new IllegalArgumentException("Non-existent state");
        }

        Integer[] colours = (Integer[]) stateToColour.get(new Integer(state));
        if (colours != null) {
            setCurrentColor(colours[0].intValue(), colours[1].intValue(), colours[2].intValue());
        } else {
            throw new IllegalArgumentException("Non-existent state");
        }

        setState(state);
    }


    /**
     *  Description of the Method
     *
     * @param  neighbourStates  Description of Parameter
     * @param  state            Description of Parameter
     * @return                  Description of the Returned Value
     */
    private boolean existsNeighboursWithState(int[][] neighbourStates,
            int state) {
        for (int x = 0; x < 3; x++) {
            for (int y = 0; y < 3; y++) {
                if (neighbourStates[x][y] == state) {
                    return true;
                }
            }
        }
        return false;
    }

    static {
        Integer[] colours = new Integer[3];
        colours[0] = new Integer(255);
        colours[1] = new Integer(255);
        colours[2] = new Integer(0);
        stateToColour.put(new Integer(SURVIVOR), colours);

        colours = new Integer[3];
        colours[0] = new Integer(204);
        colours[1] = new Integer(204);
        colours[2] = new Integer(204);
        stateToColour.put(new Integer(LAND), colours);

        colours = new Integer[3];
        colours[0] = new Integer(153);
        colours[1] = new Integer(204);
        colours[2] = new Integer(255);
        stateToColour.put(new Integer(WATER), colours);

        colours = new Integer[3];
        colours[0] = new Integer(153);
        colours[1] = new Integer(153);
        colours[2] = new Integer(153);
        stateToColour.put(new Integer(CITY), colours);

        colours = new Integer[3];
        colours[0] = new Integer(102);
        colours[1] = new Integer(254);
        colours[2] = new Integer(153);
        stateToColour.put(new Integer(FOREST), colours);

        colours = new Integer[3];
        colours[0] = new Integer(254);
        colours[1] = new Integer(22);
        colours[2] = new Integer(16);
        stateToColour.put(new Integer(BRIDGE), colours);

    }


}



