/**
 * interest.java by Payne Seal 11/21/2000
 * This program calculates compounded interest.
 */

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class interest{

	static Object[][] cells;

	static double origBal=0;
	static double intRate=0;
	static int numYears=0;
	static double amtToAdd=0;
	static String addFreq="";

	static JButton submitButton;

	static JTextField origBalTextField;
	static JTextField intRateTextField;
	static JTextField numYearsTextField;
	static JTextField amtToAddTextField;
	static JComboBox frequencyComboBox;

	static JMenuItem about;
	static JMenuItem howToUse;

	static JRadioButtonMenuItem ascending;
	static JRadioButtonMenuItem descending;
	static int sortOrder = 0; // 0=descending, 1=ascending

	static JFrame mainFrame;
	static JScrollPane scrollPane;

	static String[] columnNames = {"Year","Balance"};

	public static void main ( String[] args ){
		interest a = new interest();
		a.execute();
	}

	private void execute(){

		cells = new Object[0][2];

		mainFrame = new JFrame("Compound Interest Calculator");

		// define panels that rest on the frame
		JPanel inputPanel = new JPanel(new GridLayout(3,2));
		JPanel input2Panel = new JPanel(new GridLayout(1,4));
		JPanel buttonPanel = new JPanel(new GridLayout(1,1));
		JPanel topPanel = new JPanel(); // all of the above panels rest on this panel

		// define labels
		JLabel origBalLabel  = new JLabel("Original Balance : ");
		JLabel intRateLabel  = new JLabel("Interest Rate : ");
		JLabel numYearsLabel = new JLabel("Number of Years : ");
		JLabel amtToAddLabel = new JLabel("Amount to Add : ");
		JLabel howOftenToAddLabel = new JLabel("Every : ");

		// define textfields, etc. used for input
		origBalTextField  = new JTextField();
		intRateTextField  = new JTextField();
		numYearsTextField = new JTextField();
		amtToAddTextField = new JTextField();
		Object[] frequency = {"Day","Week","Month","Year"};
		frequencyComboBox = new JComboBox(frequency);

		// set up listeners for the textfields (so when user presses Enter, results are calculated)
		origBalTextField.addActionListener(new ListenForSubmit());
		intRateTextField.addActionListener(new ListenForSubmit());
		numYearsTextField.addActionListener(new ListenForSubmit());
		amtToAddTextField.addActionListener(new ListenForSubmit());

		// define Calculate button and set up listener
		submitButton = new JButton("Calculate!");
		submitButton.addActionListener(new ListenForSubmit());

		// add components to input panel
		inputPanel.add(origBalLabel);
		inputPanel.add(origBalTextField);

		inputPanel.add(intRateLabel);
		inputPanel.add(intRateTextField);

		inputPanel.add(numYearsLabel);
		inputPanel.add(numYearsTextField);

		// add components to input2 panel
		input2Panel.add(amtToAddLabel);
		input2Panel.add(amtToAddTextField);
		input2Panel.add(howOftenToAddLabel);
		input2Panel.add(frequencyComboBox);

		// add components to button panel
		buttonPanel.add(submitButton);

		// create top panel
		topPanel.add(inputPanel,BorderLayout.NORTH);
		topPanel.add(input2Panel,BorderLayout.CENTER);
		topPanel.add(buttonPanel,BorderLayout.SOUTH);

		// define scrollpane that will hold the results
		scrollPane = new JScrollPane(new JTable(cells,columnNames));

		// add the panels to the frame
		mainFrame.getContentPane().add(topPanel,BorderLayout.CENTER);
		mainFrame.getContentPane().add(scrollPane,BorderLayout.SOUTH);

		// define and set up menu bar
		JMenuBar menuBar = new JMenuBar();
		mainFrame.setJMenuBar(menuBar);

		// add items to the menu bar
		JMenu preferencesMenu = new JMenu("Preferences");
		JMenu fileMenu = new JMenu("Help");
		menuBar.add(preferencesMenu);
		menuBar.add(fileMenu);

		// add items to help
		about = new JMenuItem("About");
		fileMenu.add(about);
		about.addActionListener(new HandleMenu());

		howToUse = new JMenuItem("How To Use");
		fileMenu.add(howToUse);
		howToUse.addActionListener(new HandleMenu());

		// add items to preferences
		ascending = new JRadioButtonMenuItem("Sort Years Ascending",false);
		preferencesMenu.add(ascending);
		ascending.addActionListener(new HandleMenu());

		descending = new JRadioButtonMenuItem("Sort Years Descending",true);
		preferencesMenu.add(descending);
		descending.addActionListener(new HandleMenu());

		// group ascending and descending into a buttongroup
		ButtonGroup sortPreference = new ButtonGroup();
		sortPreference.add(ascending);
		sortPreference.add(descending);

		// define and display frame
		mainFrame.setBounds(300,100,400,600);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.setResizable(false);
		mainFrame.setVisible(true);

	}

	public static void calculate(){

		double runBal = origBal;
		int numDays = numYears * 365;
		int arrayIndex;

		for (int i=0;i<numDays;i++){
			if (                    addFreq.equals("Day")   ||
				(i+1) %   7 == 0 && addFreq.equals("Week")  ||
				(i+1) %  30 == 0 && addFreq.equals("Month") ||
				(i+1) % 365 == 0 && addFreq.equals("Year")){
					runBal += amtToAdd;
			}
			runBal *= (1 + intRate/365);
			//System.out.println("Day:"+i+" Balance="+commas ( new String(round(runBal,2)) ) );
			if ((i+1) % 365 == 0){
				if (sortOrder == 0){  // descending
					arrayIndex = numYears-((i+1)/365-1)-1;
				} else {              // ascending
					arrayIndex = (i+1)/365-1;
				}
				cells[arrayIndex][0] = new String(Integer.toString((i+1)/365));
				cells[arrayIndex][1] = commas ( new String(round(runBal,2)) );
			}
		}
	}

	public static String padWithSpaces(String theData , int size , String leftOrRight){
		StringBuffer returnVal = new StringBuffer();
		if (theData.length() > size){
			theData = theData.substring(0,size);
		}
		if (leftOrRight.equals("R")){
			for (int i=0;i<(size-theData.length());i++){
				returnVal.append(" ");
			}
		}
		returnVal.append(theData);
		if (leftOrRight.equals("L")){
			for (int i=0;i<(size-theData.length());i++){
				returnVal.append(" ");
			}
		}
		return returnVal.toString();
	}

	public static String round(double theNum , int numPlaces){
		double powerOf10 = Math.pow(10,numPlaces);
		double retValDouble = (Math.round(theNum * powerOf10)) / powerOf10;
		String retValString = Double.toString(retValDouble);
		StringBuffer retValStringBuffer = new StringBuffer(retValString);
		int dot = retValString.indexOf(".");
		if (retValString.length()-dot-1 < numPlaces ){
			for (int i=0;i<numPlaces-(retValString.length()-dot-1);i++){
				retValStringBuffer.append("0");
			}
		}
		return retValStringBuffer.toString();
	}

	public static String commas(String num){
		int dot = num.indexOf(".");
		if (dot == -1) dot = num.length();
		int firstComma = dot % 3;
		StringBuffer retval = new StringBuffer(num.substring(0,firstComma));
		for (int i=firstComma;i<dot;i+=3){
			if (retval.toString().length() > 0) retval.append(",");
			retval.append(num.substring(i,i+3));
		}
		retval.append(num.substring(dot));
		return retval.toString();
	}

	public static void invertTable(){
		int tableLen = cells.length;
		Object[][] tempTable = new Object[tableLen][2];
		for (int i=0;i<tableLen;i++){
			tempTable[i][0] = cells[tableLen-i-1][0];
			tempTable[i][1] = cells[tableLen-i-1][1];
		}
		cells = tempTable;
		printTable();
	}

	public static void printTable(){
		mainFrame.remove(scrollPane);
		scrollPane = new JScrollPane(new JTable(cells,columnNames));
		mainFrame.getContentPane().add(scrollPane,BorderLayout.SOUTH);
		mainFrame.setVisible(true);
	}

	class ListenForSubmit implements ActionListener{
		// handle user pressing ENTER in any field or pressing Calculate button
		public void actionPerformed(ActionEvent theEvent){
			try{
				origBal = Double.parseDouble(origBalTextField.getText());
				intRate = Double.parseDouble(intRateTextField.getText());
				numYears = Integer.parseInt(numYearsTextField.getText());
				amtToAdd = Double.parseDouble("0"+amtToAddTextField.getText()); // not a required field
				addFreq = (String)frequencyComboBox.getSelectedItem();
			}
			catch(NumberFormatException e){
				JOptionPane.showMessageDialog(null,"One or more of the input fields " +
						"contains invalid data","Error",JOptionPane.WARNING_MESSAGE);
				return;
			}
			if (intRate < 1){
				JOptionPane.showMessageDialog(null,"Warning: The interest rate " +
						"you entered is < 1.  Is this what you intended?\n" +
						"(e.g. 8% should be entered as 8, not 0.08)","Warning",
						JOptionPane.WARNING_MESSAGE);
			}
			intRate /= 100;
			cells = new Object[numYears][2];
			calculate();
			printTable();
		}
	}

	class HandleMenu implements ActionListener{
		public void actionPerformed(ActionEvent theEvent){
			int oldSortOrder = sortOrder;
			if (theEvent.getSource()==ascending){
				sortOrder = 1;
				if (sortOrder != oldSortOrder){
					invertTable();
				}
			}
			if (theEvent.getSource()==descending){
				sortOrder = 0;
				if (sortOrder != oldSortOrder){
					invertTable();
				}
			}
			if (theEvent.getSource()==about){
			    JOptionPane.showMessageDialog(null,
			    		"Interest Calculator\n"+
			    		"by Payne Seal\n"+
			    		"Copyright 2000",
			            "About Interest Calculator",
			             JOptionPane.INFORMATION_MESSAGE);
			}
			if (theEvent.getSource()==howToUse){
			    JOptionPane.showMessageDialog(null,
			    		"Enter a beginning balance in the first field\n"+
			    		"Enter the interest rate in the second field\n"+
			    		"  (e.g. 7.5% should be entered as 7.5, not as 0.075)\n"+
			    		"Enter the number of years for interest accumulation in the third field\n"+
			    		"To calculate, either press Calculate or press the ENTER key while in any field",
			            "How To Use Interest Calculator",
			             JOptionPane.INFORMATION_MESSAGE);
			}
		}
	}

}
