/** 
 *  BlackHole Source File
 *
 *  GNU Copyright (C) 2008  Gaspar Sinai gaspar(at)adys.org 
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License, version 2,
 *  dated June 1991. See file COPYYING for details.
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package sinai.gaspar.blackhole;

import java.awt.Component;

/**
 * A stoppable thread. The dream came true, threads can be stopped.
 * This class is used in BoardPanel for the applet version.
 * @author Gaspar Sinai
 * @version 2008-04-30
 */
public class TimerThread extends Thread {

    public final Object lock = new Object ();
    private long delay;
    private final Component panel;
    private PrimeStack stack;

    public static final int INIT=0; 
    public static final int RUN=1; 
    public static final int STOP=2; 
    public static final int DESTROY=3; 

    private int state = INIT;

    public TimerThread (long delay, PrimeStack stack, Component panel) {
        super ("TimerThread");
        this.delay = delay;
        this.stack = stack;
        this.panel = panel;
    }

    public void setPrimeStack (PrimeStack stack) {
        this.stack = stack;
    }

    public void th_start () {
        state = RUN;
        super.start ();
    }

    public void th_stop () {
        th_notify (STOP);
    }

    public void th_resume () {
        th_notify (RUN);
    }

    public void th_destroy () {
        th_notify (DESTROY);
    }

    // this will block till the worker thread has some time.
    public void th_notify (int newState) {
        try {
            synchronized (lock) {
                state = newState;
                lock.notify ();
            }
        } catch (Exception e) {
        }
    }

    public void setDelay (long delay) {
        try {
            synchronized (lock) {
                boolean isLess = delay < this.delay;
                this.delay = delay;
                if (isLess) lock.notify();
            }
        } catch (Exception e) {
        }
    }

    public long getDelay () {
        try {
            long ret = 0;
            synchronized (lock) {
                ret = delay;
            }
            return ret;
        } catch (Exception e) {
        }
        return 0L;
    }

    public void run () {
        while (true) {
            try {
               synchronized (lock) {
                    if (state == RUN) {
                        lock.wait (delay);
                    } 
                    if (state  == STOP) {
                        lock.wait ();
                    }
                    if (state == DESTROY) { // DESTROY or INIT
                        return;
                    }
                    if (delay != Long.MAX_VALUE) {
                        stack.forward();
                        panel.repaint();
                    }
                }
            } catch (Exception e) {
            }
        }
    }
}
