
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * Two examples for computing Fibonacci numbers
 * @author mitsunori ogihara
 *
 */
public class Fibonacci {
	// size parameters
	private final int AREA_WIDTH=70;
	private final int AREA_HEIGHT=40;
	// the only global variable
	/**
	 * String Builder
	 */ 
	private StringBuilder sb = new StringBuilder();

	/**
	 * Recursive version of the standard Fibonacci computation
	 * @param n	the number to be computed
	 * @param d	the depth of recursion
	 * @return	the F(n)
	 */
	public int stdFibo(int n, int d) {
		// print n after 2*d many '_'
		for (int i=0; i<d; i++) { this.sb.append("__"); }
		this.sb.append("n="+n+"\n");
		// compute F(n)
		int val = 0;
		if (n<=0) val = 0;
		else if (n==1) val = 1;
		else {
			val = stdFibo(n-1, d+1)+stdFibo(n-2, d+1);
		}
		// output F(n) after 2*d many '_'
		for (int i=0; i<d; i++) { this.sb.append("__"); }
		this.sb.append("F("+n+")="+val+"\n");
		return val;
	}

	/**
	 * Double-recursion Fibonacci computation, main method 
	 * @param n	the argument
	 * @return	the value of F(n)
	 */
	public int stdFiboMain(int n) {
		// reset the builder
		this.sb.delete(0, this.sb.length());
		// compute the value
		int val = this.stdFibo(n, 0);
		// create a text area and append the string in the builder
		JTextArea jta = new JTextArea(AREA_HEIGHT,AREA_WIDTH);
		jta.append(this.sb.toString());
		// create a scroll pane on the text area
		JScrollPane sp = new JScrollPane(jta);
		// and show it via JOptionPane
		JOptionPane.showMessageDialog(null, sp);
		return val;
	}
	
	/**
	 * Fast computation of Fibonacci
	 * @param fiboCurrent	the current value
	 * @param fiboPrevious	the value one before
	 * @param n	the argument	how many stpes are remaining
	 * @return	the value
	 */
	public int fiboFast(int fiboCurrent, int fiboPrevious, int n) {
		this.sb.append("n="+n+"; Current="+fiboCurrent+"; Previous="+fiboPrevious+"\n");
		// if n=1 then no more recursion
		if (n == 1) return fiboCurrent;
		// if n>1, update Current and Previous, and decrease n by 1
	 	else return fiboFast(fiboPrevious+fiboCurrent, fiboCurrent, n-1);
	 }

	/**
	 * Fast computation of Fibonacci
	 * @param n	the input
	 * @return	Fibonacci number
	 */
	public int fiboFastMain(int n) {
		// reset the string builder
		this.sb.delete(0, this.sb.length());
		// compute the value
		int val = this.fiboFast(1, 0, n);
		this.sb.append("val = " + val);
		// create a new text area, add the text
		JTextArea jta = new JTextArea(AREA_HEIGHT,AREA_WIDTH);
		jta.append(this.sb.toString());
		// create a scroll pane using the text area and show it
		JScrollPane sp = new JScrollPane(jta);
		JOptionPane.showMessageDialog(null, sp);
		return val;
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Fibonacci fb = new Fibonacci();
		while (true) {
			String w = JOptionPane.showInputDialog(
					"Standard version. Type the argument n. To quit, type a negative integer.");
			int n = Integer.parseInt(w);
			if (n<0) break;
			fb.stdFiboMain(n);
		}
		while (true) {
			String w = JOptionPane.showInputDialog(
			"Fast version. Type the argument n. To quit, type a negative integer.");
			int n = Integer.parseInt(w);
			if (n<0) break;
			fb.fiboFastMain(n);
		}		

	}

}
