/* An applet with a main window that shows a list of orders in a TextArea.  It also has buttons that when clicked open windows that can be used to add an order or find an order. */

import java.io.*;
import java.text.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;

public class OrdersAddSearch extends Applet
{
     private Panel panel, buttonPanel;
     private Label areaLabel;
     private TextArea area;
     private OrderList list;
     private Button display, showAddWindow, showSearchWindow;
     private AddWindow addWindow;
     private SearchWindow searchWindow;

     public void init ()
     {
          panel = new Panel ();
          panel.setBackground (Color.cyan);

          areaLabel = new Label ("Order");
          area = new TextArea (10, 30);
          panel.add (areaLabel); panel.add (area);

          buttonPanel = new Panel ();
          buttonPanel.setLayout (new GridLayout (3, 1, 10, 10));

          display = new Button ("Display Order");
          display.addActionListener (new DisplayListener ());
          buttonPanel.add (display);

          showAddWindow = new Button ("Show Add Window");
          showAddWindow.addActionListener (new ShowAddListener ());
          buttonPanel.add (showAddWindow);

          showSearchWindow = new Button ("Show Search Window");
          showSearchWindow.addActionListener (new ShowSearchListener ());
          buttonPanel.add (showSearchWindow);

          panel.add (buttonPanel);
          add (panel);

          list = new OrderList ();
          addWindow = new AddWindow (list);
          searchWindow = new SearchWindow (list);
          list.readOrders ();
     } // method init
 
    // Inner class that displays the list of orders when the display button is clicked.
    class DisplayListener implements ActionListener
    {
          public void actionPerformed (ActionEvent e)
          {
               list.displayOrders (area);
               list.displayTotalCost (area);
          }
     } // class DisplayListener

     // Inner class that shows the AddWindow when the addWindow button is clicked.
     class ShowAddListener implements ActionListener
     {
          public void actionPerformed (ActionEvent e) {addWindow.show ();}
     } // class ShowAddListener

     // Inner class that shows the SearchWindow when the searchWindow button is clicked.
     class ShowSearchListener implements ActionListener
     {
          public void actionPerformed (ActionEvent e) {searchWindow.show ();}
     } // class ShowSearchListener
} // class OrderFrame

/* Window that displays TextFields and Labels for the fields of an order.  It has a button that will add an order to the list. */
class AddWindow extends Frame
{
     private Panel panel, textPanel, buttonPanel;
     private Button addOrder, hideWindow;
     private TextField txtName, txtId, txtPrice, txtQuantity;
     private Label lblName, lblId, lblPrice, lblQuantity;
     private OrderList list;

     AddWindow (OrderList orderList)
     {
          super ("Add Window");
          setSize (300, 300);
          list = orderList;

          panel = new Panel ();
          panel.setBackground (Color.cyan);
          textPanel = new Panel ();
          textPanel.setLayout (new GridLayout (4, 2, 10, 10));

          txtName = new TextField (10); lblName = new Label ("Name");
          textPanel.add (lblName); textPanel.add (txtName);
          txtId = new TextField (10); lblId = new Label ("ID");
          textPanel.add (lblId); textPanel.add (txtId);
          txtPrice = new TextField (10); lblPrice = new Label ("Price");
          textPanel.add (lblPrice); textPanel.add (txtPrice);
          txtQuantity = new TextField (10); lblQuantity = new Label ("Quantity");
          textPanel.add (lblQuantity); textPanel.add (txtQuantity);
          panel.add (textPanel);

          buttonPanel = new Panel ();
          buttonPanel.setLayout (new GridLayout (2, 1, 10, 10));
          addOrder = new Button ("Add Order");
          addOrder.addActionListener (new AddListener ());
          buttonPanel.add (addOrder);

          hideWindow = new Button ("Hide");
          hideWindow.addActionListener (new HideListener ());
          buttonPanel.add (hideWindow);
          panel.add (buttonPanel);
          add (panel);
     } // constructor

     // Inner class that adds a new order when the addOrder button is clicked.
    class AddListener implements ActionListener
     {
          private String name, id;
          private double price;
          private int quantity;
          private Order newOrder;

          public void actionPerformed (ActionEvent e)
          {
               try
               {
                    name = txtName.getText ();
                    id = txtId.getText ();
                    price = Double.parseDouble (txtPrice.getText ());
                    quantity = Integer.parseInt (txtQuantity.getText ());
                    newOrder = new Order (name, id, price, quantity);
                    list.addToEnd (newOrder);
               }catch (NumberFormatException ex) {txtName.setText ("Data Error");}
          } // method actionPerformed
     } // class AddListener

     // Inner class that hides the AddWindow.
    class HideListener implements ActionListener
     {
          public void actionPerformed (ActionEvent e) {hide ();}
     } // class HideListener
} // class AddWindow

/* Window that displays TextFields and Labels to display an order after it has been found. */
class SearchWindow extends Frame
{
     private Panel panel, textPanel, buttonPanel;
     private Button searchOrder, hideWindow;
     private TextField txtName, txtId, txtPrice, txtQuantity;
     private Label lblName, lblId, lblPrice, lblQuantity;
     private OrderList list;

     SearchWindow (OrderList orderList)
     {
          super ("Search Window");
          setSize (300, 300);
          list = orderList;

          panel = new Panel ();
          panel.setBackground (Color.cyan);
          textPanel = new Panel ();
          textPanel.setLayout (new GridLayout (4, 2, 10, 10));

          txtName = new TextField (10); lblName = new Label ("Name");
          textPanel.add (lblName); textPanel.add (txtName);
          txtId = new TextField (10); lblId = new Label ("ID");
          textPanel.add (lblId); textPanel.add (txtId);
          txtPrice = new TextField (10); lblPrice = new Label ("Price");
          textPanel.add (lblPrice); textPanel.add (txtPrice);
          txtQuantity = new TextField (10); lblQuantity = new Label ("Quantity");
          textPanel.add (lblQuantity); textPanel.add (txtQuantity);
          panel.add (textPanel);

          buttonPanel = new Panel ();
          buttonPanel.setLayout (new GridLayout (2, 1, 10, 10));
          searchOrder = new Button ("Search Order");
          searchOrder.addActionListener (new SearchListener ());
          buttonPanel.add (searchOrder);

          hideWindow = new Button ("Hide");
          hideWindow.addActionListener (new HideListener ());
          buttonPanel.add (hideWindow);
          panel.add (buttonPanel);
          add (panel);
     } // constructor

     /* Inner class that  searches for an order.  If it is found, it is displayed in the TextFields.  If not, an error message is displayed. */
     class SearchListener implements ActionListener
     {
          private String name, id;
          private double price;
          private int quantity;
          private Order foundOrder;

          public void actionPerformed (ActionEvent e)
          {
               String keyId = txtId.getText ();
               Order foundOrder = list.findOrder (keyId);
               if (foundOrder == null)
               {
                    clearText ();
                    txtName.setText ("Order not found");
               }
               else
                    foundOrder.displayOrder (txtName, txtId, txtPrice, txtQuantity);
          } // method actionPerformed

          // Method that clears all TextFields.  It is used when the order is not found.
          private void clearText ()
          {
               txtName.setText ("");
               txtId.setText ("");
               txtPrice.setText ("");
               txtQuantity.setText ("");
          } // method clearText
     } // class AddListener

     // Inner class that hides the SearchWindow when the button is clicked.
     class HideListener implements ActionListener
     {
          public void actionPerformed (ActionEvent e) {hide ();}
     } // class HideListener
} // class SearchWindow

// Linked list that stores orders.  Each order is added to the end of the list.
class OrderList
{
     private Order listHead = null, listRear = null;

     // Method that reads orders from a text file and stores them in a linked list.
     public void readOrders ()
     {
          String name;
          try
          {
               BufferedReader orderFile = new BufferedReader (new InputStreamReader (new FileInputStream ("orderFile.txt")));
               name = orderFile.readLine ();
               while (name != null)
               {
                    Order order = new Order (name);
                    order.readOrder (orderFile);
                    addToEnd (order);
                    name = orderFile.readLine ();
               }
               orderFile.close ();
          }catch (IOException e) {System.out.println ("File Error");}
     } // method readOrders

     // Method that finds and order in the list and returns it to the calling method.
     public Order findOrder (String keyId)
     {
          boolean found = false;
          Order tempNode = listHead;
          while (!found && (tempNode != null))
          {
               if (tempNode.getId ().equals (keyId)) found = true;
               else tempNode = tempNode.getNext ();
          }
          if (found) return tempNode;
          else return null;
     } // method findOrder

     // Inserts a new id into the list in order by id.
     public void addToEnd (Order newOrder)
     {
          if (listHead == null)
          {
               listHead = newOrder;
               listRear = newOrder;
          }
          else
          {
               listRear.setNext (newOrder);
               listRear = newOrder;
          }
     } // method addToEnd

     // Method that displays all the orders in a TextArea.
     public void displayOrders (TextArea area)
     {
          Order tempNode = listHead;
          area.append ("Order List " + '\n' + '\n');
          while (tempNode != null)
          {
               tempNode.displayOrder (area);
               tempNode = tempNode.getNext ();
          }
     } // method displayOrders

     // Method that displays the total cost of the order at the end of the TextArea.
    public void displayTotalCost (TextArea area)
     {
          Order tempNode = listHead;
          double total = 0;
          while (tempNode != null)
          {
               total += tempNode.getPrice () * tempNode.getQuantity ();
               tempNode = tempNode.getNext ();
          }
          area.append ("Total Cost = " + NumberFormat.getCurrencyInstance ().format (total) + '\n');
     } // method totalCost
} // class OrderList

// Class that stores information about an order.
class Order
{
     private String name, id;
     private double price;
     private int quantity;
     private Order next = null;

     Order (String productName) {name = productName;} // constructor

     Order (String n, String i, double p, int q)
     {
          name = n;
          id = i;
          price = p;
          quantity = q;
    } // constructor

     protected Order getNext () { return next;}
     protected void setNext (Order newOrder) {next = newOrder;}
     protected String getId () {return id;}
     protected double getPrice () {return price;}
     protected int getQuantity () {return quantity;}

     // Method that reads one order from a text file.
     public void readOrder (BufferedReader orderFile) throws IOException
     {
          id = orderFile.readLine ();
          price = Double.parseDouble (orderFile.readLine ());
          quantity = Integer.parseInt (orderFile.readLine ());
     } // method readOrder

     // Method that displays a single order in a TextArea.
     public void displayOrder (TextArea area)
     {
          area.append ("ID: " + id + '\n');
          area.append ("Name: " + name + '\n');
          area.append ("Price: " + price + '\n');
          area.append ("Quantity: " + quantity + '\n' + '\n');
     } // method displayOrder

     // Method that displays a single order in a set of TextFields.
     public void displayOrder (TextField n, TextField i, TextField p, TextField q)
     {
          n.setText (name);
          i.setText (id);
          p.setText (NumberFormat.getCurrencyInstance ().format (price));
          q.setText (""+quantity);
     } // method displayOrder
} // class Order