package edu.cmu.cs.cs214.guidemo;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;

import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class GUIdemo extends JPanel {
	
	private long inputNumber = 1;
	private long outputNumber = 1;
	
	private final int MAX_DIGITS = 10;
	
	private final JLabel fibonacciLabel; 

	public GUIdemo() {
		JLabel inputLabel = new JLabel("Enter an input number: ");
		JFormattedTextField inputText = new JFormattedTextField(inputNumber);
		fibonacciLabel = new JLabel("fibonacci("+ inputNumber + ") is " + outputNumber);

		// compute an appropriate size for the input so it doesn't look too bad
		FontMetrics fontMetrics = inputText.getFontMetrics(inputText.getFont());
		int width = fontMetrics.getWidths()['0'] * MAX_DIGITS;
		int height = fontMetrics.getHeight();
		inputText.setPreferredSize(new Dimension(width,height));
		
		// Add the components we've created
		// Put a panel at the top with the input information
		JPanel inputPanel = new JPanel();
		inputPanel.setLayout(new BorderLayout());
		inputPanel.add(inputLabel, BorderLayout.WEST);
		inputPanel.add(inputText, BorderLayout.EAST);
		this.setLayout(new BorderLayout());
		add(inputPanel, BorderLayout.NORTH);
		
		// put the output label on the bottom
		add(fibonacciLabel, BorderLayout.SOUTH);
		
		// set up a listener to the input text
		inputText.addPropertyChangeListener("value",new PropertyChangeListener() {

			@Override
			public void propertyChange(PropertyChangeEvent evt) {
				inputNumber = (Long) evt.getNewValue();
				
				//backgroundFibonacci();
				
				outputNumber = fibonacci(inputNumber);
				displayResult();
			}			
		});
	}
	
	public static long fibonacci(long input) {
		if (input <= 2)
			return 1;
		else
			return fibonacci(input-1) + fibonacci(input-2);
	}
	
	private void displayResult() {
		fibonacciLabel.setText("fibonacci("+ inputNumber + ") is " + outputNumber);
	}

	void backgroundFibonacci() {
		SwingWorker<Long, Void> worker = new SwingWorker<Long, Void>() {
	
			@Override
			protected Long doInBackground() throws Exception {
				return fibonacci(inputNumber);
			}
			
			@Override
	        public void done() {
				try {
					outputNumber = get();
					displayResult();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
			}
		};
		
		worker.execute();
	}
	
	public static void main(String args[]) {
		// creates a main window object
		JFrame frame = new JFrame("15-214 GUI Demo");
		
		// adds a pane to the main window
		frame.add(new GUIdemo());
		
		// ensures the application will exit when the main window closes
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// sets the size of the frame to just hold its transitive components
		frame.pack();
		
		// shows the window, making the GUI interactive
		frame.setVisible(true);		
	}
	
	
}
