/*
 * Gary Cornell and Cay S. Horstmann, Core Java (Book/CD-ROM)
 * Published By SunSoft Press/Prentice-Hall
 * Copyright (C) 1996 Sun Microsystems Inc.
 * All Rights Reserved. ISBN 0-13-565755-5
 *
 * Permission to use, copy, modify, and distribute this 
 * software and its documentation for NON-COMMERCIAL purposes
 * and without fee is hereby granted provided that this 
 * copyright notice appears in all copies. 
 * 
 * THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR 
 * WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
 * AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED 
 * BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING 
 * THIS SOFTWARE OR ITS DERIVATIVES.
 */
 
/**
 * @version 1.00 07 Feb 1996 
 * @author Cay Horstmann
 */

import java.awt.*;
import java.applet.*;
import java.io.*;
import corejava.*;

public class Retire extends Applet 
{  public void init() 
   {  GridBagLayout gbl = new GridBagLayout();
      setLayout(gbl);
      
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.fill = GridBagConstraints.BOTH;
      gbc.weightx = 100;
      gbc.weighty = 100;
      add(new Label("Prior Savings"), gbl, gbc, 0, 0, 1, 1);
      add(savingsField, gbl, gbc, 1, 0, 1, 1);
      add(new Label("Annual Contribution"), 
         gbl, gbc, 2, 0, 1, 1);
      add(contribField, gbl, gbc, 3, 0, 1, 1);
      add(new Label("Retirement Income"), 
         gbl, gbc, 4, 0, 1, 1);
      add(incomeField, gbl, gbc, 5, 0, 1, 1);
      add(new Label("Current Age"), gbl, gbc, 0, 1, 1, 1);
      add(currentAgeField, gbl, gbc, 1, 1, 1, 1);
      add(new Label("Retirement Age"), gbl, gbc, 2, 1, 1, 1);
      add(retireAgeField, gbl, gbc, 3, 1, 1, 1);
      add(new Label("Life Expectancy"), gbl, gbc, 4, 1, 1, 1);
      add(deathAgeField, gbl, gbc, 5, 1, 1, 1);
      add(new Label("% Inflation"), gbl, gbc, 0, 2, 1, 1);
      add(inflationPercentField, gbl, gbc, 1, 2, 1, 1);
      add(new Label("% Invest Return"), gbl, gbc, 2, 2, 1, 1);
      add(investPercentField, gbl, gbc, 3, 2, 1, 1);
      add(new Button("Compute"), gbl, gbc, 5, 2, 1, 1);
      add(retireCanvas, gbl, gbc, 0, 3, 4, 1);
      add(retireText, gbl, gbc, 4, 3, 2, 1);
      retireText.setEditable(false);
      retireText.setFont(new Font("Courier", Font.PLAIN, 10));
   }
      
   private void add(Component c, GridBagLayout gbl, 
      GridBagConstraints gbc, int x, int y, int w, int h)
   {  gbc.gridx = x;
      gbc.gridy = y;
      gbc.gridwidth = w;
      gbc.gridheight = h;
      gbl.setConstraints(c, gbc);
      add(c);
   }
   
   public boolean action(Event evt, Object arg)
   {  if (arg.equals("Compute"))
      {  if (savingsField.isValid() 
            && contribField.isValid()
            && incomeField.isValid() 
            && currentAgeField.isValid()
            && retireAgeField.isValid()
            && deathAgeField.isValid()
            && inflationPercentField.isValid()
            && investPercentField.isValid())
         {  RetireInfo info = new RetireInfo();
            info.savings = savingsField.getValue();
            info.contrib = contribField.getValue();
            info.income = incomeField.getValue();
            info.currentAge = currentAgeField.getValue();
            info.retireAge = retireAgeField.getValue();
            info.deathAge = deathAgeField.getValue();
            info.inflationPercent 
               = inflationPercentField.getValue();
            info.investPercent 
               = investPercentField.getValue();
            retireCanvas.redraw(info);
            int i;
            retireText.setText("");            
            for (i = info.currentAge; i <= info.deathAge; i++)
            {  retireText.appendText(
                  new Format("Age: %3d").form(i)
                     + new Format(" Balance: %8d\n")
                     .form(info.getBalance(i)));
            }
         }
      }
      else return super.action(evt, arg);
      return true;
   }

   private IntTextField savingsField 
      = new IntTextField(0, 0, 10000000, 10);      
   private IntTextField contribField 
      = new IntTextField(9000, 0, 1000000, 10);      
   private IntTextField incomeField 
      = new IntTextField(0, 0, 1000000, 10);      
   private IntTextField currentAgeField 
      = new IntTextField(0, 0, 150, 4);      
   private IntTextField retireAgeField 
      = new IntTextField(65, 0, 150, 4);      
   private IntTextField deathAgeField 
      = new IntTextField(85, 0, 150, 4);      
   private IntTextField inflationPercentField 
      = new IntTextField(5, 0, 1000, 4);      
   private IntTextField investPercentField 
      = new IntTextField(10, 0, 1000, 4);      
   private RetireCanvas retireCanvas = new RetireCanvas();  
   private TextArea retireText = new TextArea(10, 25);
}

class RetireInfo
{  public int getBalance(int year)
   {  if (year < currentAge) return 0;
      else if (year == currentAge) 
      {  age = year;
         balance = savings;
         return balance;
      }
      else if (year == age)
         return balance;
      if (year != age + 1) 
         getBalance(year - 1);
      age = year;
      if (age < retireAge) 
         balance += contrib; 
      else
         balance -= income;
      balance = (int)(balance 
         * (1 + (investPercent - inflationPercent) / 100.0));
      return balance;
   }

   int savings;
   int contrib;
   int income;
   int currentAge;
   int retireAge;
   int deathAge;
   int inflationPercent;
   int investPercent;
   
   private int age;
   private int balance;
}

class RetireCanvas extends Canvas
{  public RetireCanvas() 
   {  resize(400, 200);
   }
   public void redraw(RetireInfo newInfo)
   {  info = newInfo;
      repaint();
   }

   public void paint(Graphics g)
   {  if (info == null) return;
      
      int minValue = 0;
      int maxValue = 0;
      int i;
      for (i = info.currentAge; i <= info.deathAge; i++)
      {  int v = info.getBalance(i);
         if (minValue > v) minValue = v;
         if (maxValue < v) maxValue = v;
      }
      if (maxValue == minValue) return;
            
      Dimension d = size();
      int barWidth = d.width / (info.deathAge 
         - info.currentAge + 1);
      double scale = (double)d.height 
         / (maxValue - minValue);
      
      for (i = info.currentAge; i <= info.deathAge; i++)
      {  int x1 = (i - info.currentAge) * barWidth + 1;
         int y1;
         int v = info.getBalance(i);
         int height;
         int yOrigin = (int)(maxValue * scale);

         if (v >= 0)
         {  y1 = (int)((maxValue - v) * scale);
            height = yOrigin - y1;
         }
         else
         {  y1 = yOrigin;
            height = (int)(-v * scale);
         }
  
         if (i < info.retireAge)
            g.setColor(Color.blue);
         else if (v >= 0)
            g.setColor(Color.green);
         else
            g.setColor(Color.red);
         g.fillRect(x1, y1, barWidth - 2, height);         
         g.setColor(Color.black);
         g.drawRect(x1, y1, barWidth - 2, height);
      }
   }
   
   private RetireInfo info = null;
}
