import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FibStartStop extends JFrame implements ActionListener {
    private JTextField numField, seqField, statusField;
    private JButton start, stop;
    private FibThread ft;
    private Timer t;
    
    public FibStartStop() {
        setTitle("Fibonacci");
        setSize(1000, 100);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        Container pane = getContentPane();
        pane.setLayout(new FlowLayout());
        
        numField = new JTextField(10);
        pane.add(numField);
        
        start = new JButton("Compute Fibonacci");
        start.addActionListener(this);
        pane.add(start);
        
        stop = new JButton("Stop");
        stop.addActionListener(this);
        pane.add(stop);
        
        statusField = new JTextField(10);
        pane.add(statusField);
        
        seqField = new JTextField(80);
        pane.add(seqField);
        
        t = new Timer(10, this);
        ft = null;
    }
    
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == start && ft == null) {
            ft = new FibThread(Integer.parseInt(numField.getText()));
            ft.start();
            t.start();
            statusField.setText("running...");
        } else if (e.getSource() == stop && ft != null) {
            ft.endComputation();
        } else if (e.getSource() == t) {
            seqField.setText(ft.getResult());
            if (ft.isFinished()) {
                t.stop();
                statusField.setText("done");
                ft = null;
            }
        }
    }
    
    private class FibThread extends Thread {
        private int max;
        private String result;
        private boolean stillGoing;
        
        public FibThread(int value) {
            max = value;
            result = "";
            stillGoing = false;
        }
        
        public void run() {
            stillGoing = true;
            for (int i = 0; stillGoing && i <= max; ++i) {
                int f = computeFib(i);
                if (stillGoing) {result += " " + f;}
            }
            stillGoing = false;
        }
        
        public void endComputation() {stillGoing = false;}
        
        public String getResult() {return result;}
        
        public boolean isFinished() {return !stillGoing;}
        
        private int computeFib(int f) {
            if (stillGoing) {
                if (f < 2) {return 1;}
                else {
                    return computeFib(f - 1) + computeFib(f - 2);
                }
            } else {
                return 0;
            }
        }
    }
    
    public static void main(String[] args) {
        FibStartStop f = new FibStartStop();
        f.setVisible(true);
    }
}
