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

    // Maintain a Timer linked to a JProgressBar.
    // At every timer increment, adjust the bar by the
    // step attribute value.
class TapeDemo extends JFrame implements ActionListener {
        // Set up the GUI buttons. These delegate to the VCR.
    public TapeDemo(String title,final VCR vcr){
        final int width = 500, height = 300;
        setTitle(title);
        setSize(width,height);
        Container contents = getContentPane();

        contents.add(getTapeName(),"North");
        final JProgressBar bar = getBar();     
        bar.setPreferredSize(new Dimension(width,40));
        bar.setBackground(Color.white);
        contents.add(bar,"Center");

        // The panel for the control buttons.
        JPanel buttonPanel = new JPanel();
        buttonPanel.setBackground(Color.white);
        JButton stop = new JButton("Stop");
        stop.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                vcr.stop();
            }
        });
        buttonPanel.add(stop);
        JButton rew = new JButton("Rew");
        rew.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                vcr.rew();
            }
        });
        buttonPanel.add(rew);
        JButton play = new JButton("Play");
        play.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                vcr.play();
            }
        });
        buttonPanel.add(play);
        JButton pause = new JButton("Pause");
        pause.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                vcr.pause();
            }
        });
        buttonPanel.add(pause);
        JButton ff = new JButton("FF");
        ff.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                vcr.ff();
            }
        });
        buttonPanel.add(ff);
        contents.add(buttonPanel,"South");

        this.vcr = vcr;
        pack();
        addWindowListener(new WindowCloser());
        setVisible(true);
    }
    
    public void start(int speed){
        setStep(speed);
        getTimer().start();
    }

    public void pause(){
        getTimer().stop();
    }

    public void stop(){
        getTimer().stop();
    }

    public void reset(){
        getTimer().stop();
        getBar().setValue(0);
        setStep(1);
    }

    private void rewind(){
        getVCR().rew();
    }

    public void forward(){
        getVCR().ff();
    }

    public void changeTape(String tape){
        getTapeName().setText(tape);
        reset();
    }

        // The timer has pinged.
    public void actionPerformed(ActionEvent e){
        JProgressBar bar = getBar();
        int step = getStep();
        bar.setValue(bar.getValue()+step);
        if(step > 0){
            if(bar.getPercentComplete() >= 1.0){
                bar.setValue(bar.getMaximum());
                getVCR().stop();
            }
        }
        else{
            if(bar.getPercentComplete() <= 0.0){
                bar.setValue(bar.getMinimum());
                getVCR().stop();
            }
        }
    }

    private Timer getTimer(){
        return timer;
    }

    private JProgressBar getBar(){
        return bar;
    }

    private JTextField getTapeName(){
        return tapeName;
    }

    private VCR getVCR(){
        return vcr;
    }

    private int getStep(){
        return step;
    }

    private void setStep(int s){
        getTimer().setDelay((int) Math.abs(timeIncrement*1.0/s));
        step = s;
    }

    // How many milliseconds to update each step.
    private static final int timeIncrement = 350;
    // Limits of the progress bar (length of the tape).
    private static final int min = 0, max = 600;

    // A display for the tape's name.
    private JTextField tapeName = new JTextField();
    {
        tapeName.setHorizontalAlignment(JTextField.HORIZONTAL);
        tapeName.setEditable(false);
        tapeName.setBackground(Color.white);
    }
    // At every timeIncrement, the Timer notifies this object to
    // update the progress bar.
    private final Timer timer = new Timer(timeIncrement,this);
    private JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL,
                                min,max);
    // How far the progress bar moves at each ping. This will be
    // +ve in play and ff modes, and negative in rew.
    private int step = 1;
    // The VCR for which this is the GUI.
    final private VCR vcr;
}
