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

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.actsofgod;

import gecco.server.automaton.*;
import gecco.server.qmanager.*;

import java.util.*;

/**
 *  Description of the Class
 *
 * @author     Karl Hasselström
 * @created    June 27, 2001
 */
public class ActsOfGod extends Thread {
    /**
     *  Description of the Field
     */
    private TreeSet acts;
    /**
     *  Description of the Field
     */
    private Act next;
    /**
     *  Description of the Field
     */
    private QManager qm;


    /**
     *  Constructor for the ActsOfGod object
     *
     * @param  qm  Description of Parameter
     */
    public ActsOfGod(QManager qm) {
        super("Acts of God");
        acts = new TreeSet();
        next = null;
        this.qm = qm;
    }


    /**
     *  Adds a feature to the Act attribute of the ActsOfGod object
     *
     * @param  eventName       The feature to be added to the Act attribute
     * @param  factor          The feature to be added to the Act attribute
     * @param  x               The feature to be added to the Act attribute
     * @param  y               The feature to be added to the Act attribute
     * @param  secondsFromNow  The feature to be added to the Act attribute
     */
    public void addAct(String eventName, int factor, double x, double y,
            double secondsFromNow) {
        // Create the act.
        AutomatonEvent ae = new AutomatonEvent(eventName, factor);
        long time = Math.round(secondsFromNow * 1000.0) +
                System.currentTimeMillis();
        Act a = new Act(ae, x, y, time);

        // Add it to the list
        synchronized (acts) {
            acts.add(a);
        }

        // Interrupt the thread carrying out the acts in case the new
        // act should go first
        this.interrupt();
    }


    /**
     *  Main processing method for the ActsOfGod object
     */
    public void run() {

        // Loop forever
        while (true) {

            // Get next act, or go to sleep if there is none.
            try {
                synchronized (acts) {
                    next = (Act) acts.first();
                }
            } catch (NoSuchElementException e) {

                // Sleep for a second ...
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e2) {
                    // This just means we were woken early. Go on as
                    // usual.
                }

                // ... then go get next act!
                continue;
            }

            // Wait for the right time.
            long timeLeft = next.getTime() - System.currentTimeMillis();
            if (timeLeft > 0) {
                try {
                    Thread.sleep(timeLeft);
                } catch (InterruptedException e) {
                    // Someone has changed the set of acts. We need to start over!
                    continue;
                }
            }

            // Carry out the act and remove it from the todo list
            AutomatonEvent act = next.getAct();
            int x = (int) next.getX();
            int y = (int) next.getY();
            qm.addEventToQueue(act, x, y);
            acts.remove(next);

            // Tell the world
            System.out.println("Act of God '" + act.getEventName() + "' effected.");
            System.out.println("\tFactor = " + act.getFactor() + ", position = ("
                     + x + "," + y + ").");
        }
    }
}
