/**
 * Copyright (c) 2005 Red Hat, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Component of: Red Hat Application Server
 *
 * Initial Developers: Gregory Lapouchnian
 *                     Patrick Smith
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */
package olstore.client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPMessage;

import org.apache.axis.client.Call;

/**
 * A GUI client that allows to use some of the functionality of the OLStore
 * example by connecting to its web service endpoint.
 */
public class OlstoreSwingClient implements ActionListener {

    /** The default URL for the web service. */
    private static String url = "http://localhost:9000/axis-olstorews";

    /** The path for the olstoreEndpoint. */
    private static String storeEndpointPath = "/olstoreEndpoint/ItemSpecialHelperLocal";

    /** The path for the wsShoppingCartHelper endpoint. */
    private static String cartEndpointPath = "/wsShoppingCartHelper/ShoppingCartHelperLocal";

    /** The button to retrieve all specials. */
    private JButton bSpecials;

    /** The button to select the type of specials. */
    private JButton bSpecialsByType;

    /** The button to empty the shopping cart. */
    private JButton bEmpty;

    /**
     * Progress bar that indicates that the client is in the process of
     * retrieving the information from the web service.
     */
    private JProgressBar progressBar;

    /** The main window of the client. */
    private JFrame frame;

    /** The main panel of the client. */
    private JPanel panel;

    /** The scroll pane which contains the displayed items. */
    private JScrollPane scrollPane;

    /** The "Exit" menu item. */
    private JMenuItem exitMenuItem;

    /**
     * The Call object that is used to send/receive information via the web
     * service.
     */
    private Call call;

    /** Contains the different types of items available from the olstore. */
    private String[] types;

    /**
     * The panel which holds the "Get all specials" and "Specials by type"
     * buttons.
     */
    private JPanel buttonPane;

    /** Provide a way to modify the URL of the web serice. */
    private JPanel urlPane;

    /** The field which contains the URL to access the web services from. */
    private JTextField urlField = new JTextField(url);

    /** A label for the url pane. */
    private JLabel urlLabel = new JLabel("Web Service URL:");

    /** The handler to drag and drop items into the shopping cart. */
    private ItemPanelTransferHandler handler;

    /** The panel which contains shopping cart related components. */
    private JPanel cartPanel;

    /** The panel which contains the individual order items in the shopping cart. */
    private ShoppingCartPanel cartMainPanel;

    /** The shopping cart's total price. */
    private JLabel totalPrice;

    /** The checkout button. */
    private JButton bCheckout;

    /** The value of the shopping cart's total price. */
    private BigDecimal priceValue = new BigDecimal(0.00f);

    /** The primary item colour */
    public static final Color itemColor1 = new Color(139, 147, 171);

    /** The secondary item colour */
    public static final Color itemColor2 = new Color(180, 185, 200);

    /** The colour of buttons. */
    public static final Color buttonColor = new Color(115, 160, 195);

    /** The formatter used to display the prices with 2 decimal places. */
    private static DecimalFormat formatter = new DecimalFormat("#0.00");

    /** The scroll pane which individual order items are placed in. */
    private JScrollPane cartScrollPane;

    /** The maximum of the JProgressBar */
    private static final int PROGRESSMAX = 100;

    /** Used for small pane sizing. */
    private static final int PANESIZE_SMALL = 300;

    /** Used for pane sizing. */
    private static final int PANESIZE_MEDIUM = 500;

    /** Used for slightly larger pane sizing. */
    private static final int PANESIZE = 600;

    /** Used for larger pane sizing. */
    private static final int PANESIZE_LARGE = 800;

    /** Used for small spacers. */
    private static final int SPACER = 15;

    /** Used for large spacers. */
    private static final int LARGE_SPACER = 200;

    /** Used for defining a maximum pane height. */
    private static final int PANEL_HEIGHT = 30;

    /** Used for defining a maximum banner height. */
    private static final int BANNER_HEIGHT = 80;

    /** Used for selecting between getting the WSDL from a textfield or the UDDI registry. */
    private ButtonGroup bGroup = new ButtonGroup();

    /** Used to get the WSDL url from the textfield. */
    private JRadioButton bURL = new JRadioButton("Use Web Service URL:");

    /** Used to get the WSDL url from the UDDI registry */
    private JRadioButton bDiscover = new JRadioButton("Discover via UDDI");

    /** Connect to the UDDI registry to retrieve WSDL URLs. */
    private RegistryConnector registryConnector = new RegistryConnector();

    /**
     * The constructor which creates the components and places them into the
     * appropriate layouts.
     */
    public OlstoreSwingClient() {
        handler = new ItemPanelTransferHandler();
        frame = new JFrame("Olstore Swing Client");

        // the buttons to display all specials
        bSpecials = new JButton("Get All Specials");
        bSpecials.addActionListener(this);

        // the button to select specials from a single category
        bSpecialsByType = new JButton("Specials By Type");
        bSpecialsByType.addActionListener(this);

        // the button to checkout the shopping cart
        bCheckout = new JButton("Checkout");
        bCheckout.addActionListener(this);

        // the button to empty the shopping cart.
        bEmpty = new JButton("Empty Cart");
        bEmpty.addActionListener(this);
        bEmpty.setBackground(buttonColor);

        // initialize the progress bar
        progressBar = new JProgressBar(0, PROGRESSMAX);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        progressBar.setString("");

        // the main area where all the special are displayed
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());

        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBackground(itemColor1);
        scrollPane = new JScrollPane(panel);
        scrollPane.setMinimumSize(new Dimension(PANESIZE_MEDIUM,
                PANESIZE_MEDIUM));
        scrollPane.setPreferredSize(new Dimension(PANESIZE_LARGE, PANESIZE));

        // add a menu to this application
        createMenu();

        // creates and fills the url panel.
        urlPane = new JPanel();
        urlPane.setLayout(new BoxLayout(urlPane, BoxLayout.X_AXIS));
        urlPane.add(urlLabel);
        urlPane.add(urlField);
        urlPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, PANEL_HEIGHT));

        buttonPane = new JPanel();
        buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
        bSpecials.setBackground(buttonColor);
        bSpecialsByType.setBackground(buttonColor);

        buttonPane.add(bSpecials);
        buttonPane.add(bSpecialsByType);

        JPanel bannerPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        bannerPanel.setBackground(Color.BLACK);
        bannerPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE,
                BANNER_HEIGHT));
        JLabel shadowMan = new JLabel(new ImageIcon("images/olstoreLogo.png"));
        bannerPanel.add(shadowMan);

        addExplanationPanel();

        // create a shopping cart panel
        cartPanel = new JPanel();
        cartPanel.setLayout(new BorderLayout());
        cartPanel.add(new JLabel("Shopping Cart"), BorderLayout.NORTH);

        cartMainPanel = new ShoppingCartPanel(this);
        cartMainPanel.setTransferHandler(handler);
        cartMainPanel.setLayout(new BoxLayout(cartMainPanel, BoxLayout.Y_AXIS));
        cartMainPanel.setBackground(itemColor1);

        totalPrice = new JLabel("Your total: $0.00");
        JPanel checkoutPanel = new JPanel();
        checkoutPanel.setLayout(new BoxLayout(checkoutPanel, BoxLayout.X_AXIS));
        checkoutPanel.add(totalPrice);
        checkoutPanel.add(Box.createHorizontalStrut(SPACER));
        checkoutPanel.add(bCheckout);
        checkoutPanel.add(bEmpty);
        checkoutPanel.setBackground(itemColor1);
        bCheckout.setBackground(buttonColor);
        cartPanel.add(checkoutPanel, BorderLayout.SOUTH);

        cartScrollPane = new JScrollPane(cartMainPanel);
        cartScrollPane.setMinimumSize(new Dimension(PANESIZE_SMALL,
                PANESIZE_MEDIUM));
        cartScrollPane.setBackground(itemColor1);
        cartPanel.add(cartScrollPane, BorderLayout.CENTER);
        cartPanel.setBackground(itemColor1);
        // the split pane to display products and the shopping cart side by side
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                scrollPane, cartPanel);
        splitPane.setBackground(itemColor1);
        splitPane.setForeground(itemColor1);
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
        topPanel.add(bannerPanel);
        topPanel.add(buttonPane);
        topPanel.setBackground(Color.BLACK);

        bURL.setSelected(true);
        bGroup.add(bURL);
        bGroup.add(bDiscover);
        bURL.addActionListener(this);
        bDiscover.addActionListener(this);

        JPanel discoverPanel = new JPanel();
        discoverPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        discoverPanel.add(bDiscover);
        // creates and fills the url panel.
        urlPane = new JPanel();
        urlPane.setLayout(new BoxLayout(urlPane, BoxLayout.X_AXIS));
        urlPane.add(bURL);
        urlPane.add(urlField);
        urlPane.add(progressBar);
        urlPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, PANEL_HEIGHT));

        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
        bottomPanel.add(discoverPanel);
        bottomPanel.add(urlPane);

        mainPanel.add(topPanel, BorderLayout.NORTH);
        mainPanel.add(splitPane, BorderLayout.CENTER);
        mainPanel.add(bottomPanel, BorderLayout.SOUTH);
        mainPanel.setBackground(itemColor1);
        frame.getContentPane().add(mainPanel);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }

    /**
     * Create a panel that gives the user instructions on how to use the client
     * on startup.
     */
    private void addExplanationPanel() {

        panel.setLayout(new BorderLayout());

        JPanel explainPanel = new JPanel();
        explainPanel.setPreferredSize(new Dimension(200, 100));
        explainPanel.setLayout(new BoxLayout(explainPanel, BoxLayout.Y_AXIS));
        explainPanel.setBackground(itemColor2);

        JLabel label0 = new JLabel("Welcome to OLStore");
        label0.setFont(new Font("sans-serif", Font.BOLD, 17));
        explainPanel.add(label0);
        explainPanel.add(Box.createVerticalStrut(SPACER));
        explainPanel
                .add(new JLabel(
                        "To view all the specials click the 'All Specials' button above."));

        explainPanel.add(Box.createVerticalStrut(SPACER));
        explainPanel
                .add(new JLabel(
                        "To view the specials by type click the 'Specials By Type' button."));
        explainPanel.add(Box.createVerticalStrut(SPACER));
        explainPanel.add(new JLabel(
                "To add an item to the shopping cart, simply drag it to the "));
        explainPanel.add(new JLabel("shopping cart panel on the right."));

        panel.add(explainPanel, BorderLayout.CENTER);
        panel.add(Box.createVerticalStrut(LARGE_SPACER),
                BorderLayout.PAGE_START);
        panel.add(Box.createHorizontalStrut(LARGE_SPACER),
                BorderLayout.LINE_START);
        panel.add(Box.createVerticalStrut(LARGE_SPACER), BorderLayout.PAGE_END);
        panel.add(Box.createHorizontalStrut(LARGE_SPACER),
                BorderLayout.LINE_END);
    }

    /**
     * Creates and displays a new olstore client.
     * @param args The program's arguments.
     */
    public static void main(String[] args) {
        OlstoreSwingClient client = new OlstoreSwingClient();
    }

    /**
     * Creates a menu bar and adds an 'Exit' menu item.
     */
    public void createMenu() {
        JMenuBar menuBar = new JMenuBar();

        JMenu menu = new JMenu("File");
        menu.setMnemonic(KeyEvent.VK_F);
        menuBar.add(menu);

        exitMenuItem = new JMenuItem("Exit", KeyEvent.VK_E);
        exitMenuItem.addActionListener(this);

        menu.add(exitMenuItem);

        frame.setJMenuBar(menuBar);
    }

    /**
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent event) {
        try {
            if (event.getSource().equals(bSpecials)) {
                // Create a new thread to execute the call to the web service
                // while allowing the GUI thread to update the progress bar
                new Thread() {
                    public void run() {
                        try {
                            displaySpecials("allSpecials", null);
                        } catch (Exception ex) {
                            reportError(ex);
                        }
                    }
                }.start();
            }
            if (event.getSource().equals(bSpecialsByType)) {
                if (types == null) {
                    new Thread() {
                        public void run() {
                            try {
                                getSpecialTypes();
                                displayTypes();
                            } catch (Exception ex) {
                                reportError(ex);
                            }
                        }
                    }.start();
                } else {
                    displayTypes();
                }

            }
            if (event.getSource().equals(bCheckout)) {
                doCheckout();

            }
            if (event.getSource().equals(bDiscover)) {
                urlField.setEnabled(false);
            }
            if (event.getSource().equals(bURL)) {
                urlField.setEnabled(true);
            }

            if (event.getSource().equals(bEmpty)) {
                cartMainPanel.removeAllItems();
            }
            if (event.getSource().equals(exitMenuItem)) {
                int n = JOptionPane.showConfirmDialog(frame,
                        "Do you want to exit the client?", "Exit",
                        JOptionPane.YES_NO_OPTION);

                if (n == 0) {
                    System.exit(0);
                }
            }

        } catch (Exception e) {
            reportError(e);
        }

    }

    /**
     * Contacts the web service via the base URL entered in the urlField, and
     * the defined store endpoint, and stores the types in the String[]
     * <code>types</code>.
     */
    private void getSpecialTypes() {
        // start the progress bar
        progressBar.setIndeterminate(true);
        progressBar.setString("Loading types...");
        bSpecialsByType.setEnabled(false);

        try {
            call = new Call(getStoreEndpoint());
            types = (String[]) (call.invoke("getTypes", null));
        } catch (Exception e) {
            reportError(e);
        }

        bSpecialsByType.setEnabled(true);
        // stop the progress bar
        progressBar.setIndeterminate(false);
        progressBar.setString("Done");

    }

    /**
     * Prompts the user which type (via <code>types</code>) of special they
     * would like to view, and displays the specials of that type.
     */
    private void displayTypes() {
        if (types != null) {
            final String s = (String) JOptionPane.showInputDialog(frame,
                    "Select a type...", "Choose A Type",
                    JOptionPane.PLAIN_MESSAGE, null, types, null);

            if ((s != null) && (s.length() > 0)) {
                new Thread() {
                    public void run() {
                        try {
                            displaySpecials("getSpecials", new Object[] { s });
                        } catch (Exception ex) {
                            reportError(ex);
                        }
                    }
                }.start();
            }
        }
    }

    /**
     * Given a method name and array of parameters, invokes the web service
     * through Call.invoke passing it the method name and parameters. The web
     * service's response consists of a String[][] which contains the
     * information for each item, as well as an image attachment for each item.
     * The information and image are used to create new items which are
     * displayed in the scroll pane.
     * @param method The name of the method to invoke.
     * @param params The parameters for the method.
     * @throws Exception If the call fails.
     */
    private void displaySpecials(String method, Object[] params)
            throws Exception {

        // set the layout to BoxLayout, it might have been different to display
        // the welcome screen
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        // start the progress bar
        progressBar.setIndeterminate(true);
        progressBar.setString("Loading specials...");

        // disable the appropriate button while the webservice is called
        if (params == null) {
            bSpecials.setEnabled(false);
        } else {
            bSpecialsByType.setEnabled(false);
        }

        call = new Call(getStoreEndpoint());

        String[][] result = (String[][]) (call.invoke(method, params));

        SOAPMessage msg = call.getResponseMessage();
        Iterator j = msg.getAttachments();
        int counter = 0;
        Color color;

        // empty the current contents of this panel
        panel.removeAll();

        while (j.hasNext()) {
            AttachmentPart ap = (AttachmentPart) j.next();

            BufferedImage bi = ImageIO.read(ap.getDataHandler()
                    .getInputStream());

            if (counter % 2 == 0) {
                color = itemColor1;
            } else {
                color = itemColor2;
            }

            ItemPanel itemPanel = new ItemPanel(result[counter][1],
                    result[counter][2], result[counter][3], result[counter][0],
                    result[counter][4], bi, color);

            itemPanel.setBackground(color);
            panel.add(itemPanel);

            itemPanel.setTransferHandler(handler);

            counter++;
        }
        // make sure the new components are drawn
        scrollPane.validate();
        scrollPane.repaint();

        // turn the button back on
        if (params == null) {
            bSpecials.setEnabled(true);
        } else {
            bSpecialsByType.setEnabled(true);
        }
        // set the flag for the timer
        progressBar.setIndeterminate(false);
        progressBar.setString("Done");

    }

    /**
     * Get the web services endpoint URL for OLStore. Returns the URL from UDDI
     * registry if the bDiscover radio button is selected, uses the URL from the
     * textfield otherwise.
     *
     * @return the URL of OLStore web services endpoint
     * @throws Exception if it is unable to retrieve it from the UDDI registry
     */
    private String getStoreEndpoint() throws Exception {
        // only connect to the UDDI registry if the 'Discover' radio button is on
        if (bDiscover.isSelected()) {
            try {
                registryConnector.retrieveWSDLLocations();
            } catch (Exception e) {
                throw new Exception("Could not retrieve the WSDL URLs from the registry. " + e.getMessage());
            }

            List locations = registryConnector.getCartWSDLLocations();

            if (locations.isEmpty()) {
                throw new Exception("No WSDL URL was returned.");
            } else {
                // TODO provide the user with a list of available URLs?
                return (String) registryConnector.getSpecialsWSDLLocations().get(0);
            }
        }

        // return the endpoint by combining the value in the urlField with the
        // constant for the endpoint
        return urlField.getText() + storeEndpointPath;
    }

    /**
     * Get the web services endpoint URL for OLStore shopping cart. Returns the
     * URL from UDDI registry if the bDiscover radio button is selected, uses
     * the URL from the textfield otherwise.
     *
     * @return the URL of OLStor shopping cart web services endpoint
     * @throws Exception if it is unable to retrieve it from the UDDI registry
     */
    private String getShoppingCartEndpoint() throws Exception {
        // only connect to the UDDI registry if the 'Discover' radio button is on
        if (bDiscover.isSelected()) {
            try {
                registryConnector.retrieveWSDLLocations();
            } catch (Exception e) {
                throw new Exception("Could not retrieve the WSDL URLs from the registry. " + e.getMessage());
            }

            List locations = registryConnector.getCartWSDLLocations();

            if (locations.isEmpty()) {
                throw new Exception("No WSDL URL was returned.");
            } else {
                System.out.println("using registry URL: " + (String) registryConnector.getCartWSDLLocations().get(0));
                return (String) registryConnector.getCartWSDLLocations().get(0);
            }
        }

        // return the endpoint by combining the value in the urlField with the
        // constant for the endpoint
        return urlField.getText() + cartEndpointPath;
    }

    /**
     * Reports the given exception via a JOptionPane.
     * @param e The exception to report.
     */
    private void reportError(Exception e) {
        JOptionPane.showMessageDialog(frame,
                "Could not retrieve the required information from OLStore.\nError: "
                        + e.getMessage(), "Client error",
                JOptionPane.ERROR_MESSAGE);

        // turn off the progress bar
        progressBar.setIndeterminate(false);
        progressBar.setString("Error");

        // turn on the buttons
        bSpecialsByType.setEnabled(true);
        bSpecials.setEnabled(true);
    }

    /**
     * Updates the price value and price field by adding the given price to the
     * current total.
     * @param price The amount to add to the current total.
     */
    public void updatePrice(BigDecimal price) {
        priceValue = priceValue.add(price);
        setPrice(priceValue);
    }

    /**
     * Sets the price label to the given price.
     * @param priceValue The value to set the price label to.
     */
    public void setPrice(BigDecimal priceValue) {
        this.priceValue = priceValue;
        totalPrice.setText("Your total: $" + formatter.format(priceValue));
    }

    /**
     * Prompts the user for a username and password, and sends the login
     * information and cart contents (item IDs and the corresponding quantities)
     * to the server via web services. If the login information is accepted the
     * cart contents are added to a server side, user specific, shopping cart
     * and the order is created and completed. If the login information is
     * incorrect, then the user is prompted to try again.
     * @throws Exception If the call fails.
     */
    public void doCheckout() throws Exception {

        if (cartMainPanel.isEmpty()) {
            JOptionPane.showMessageDialog(frame,
                    "The shopping cart does not contain any items.",
                    "Empty Cart", JOptionPane.INFORMATION_MESSAGE);
        } else {
            LoginDialog ld = new LoginDialog(frame);
            ld.show();
            if (ld.login()) {
                String[] info = ld.getLogin();

                Boolean result = new Boolean(false);

                Object[] orderItems = cartMainPanel.getCartContents();
                String[][] contents = new String[orderItems.length][2];
                for (int i = 0; i < orderItems.length; i++) {
                    OrderItem item = (OrderItem) orderItems[i];
                    contents[i][0] = item.getId();
                    contents[i][1] = String.valueOf(item.getQuantity());
                }

                Object[] params = new Object[] { info[0], info[1],
                        (String[][]) contents };

                call = new Call(getShoppingCartEndpoint());

                // Not the best way to handle sending the parameters, but in
                // order to
                // send the String[][] that contains the shopping cart item IDs
                // and
                // quantities, we have to use addParameter.
                // For some strange reason this results in the 2-dimensional
                // array being sent as a 4-dimensional array through the
                // web service, though on the server side, it is still received
                // as a 2-dimensional array.
                call.addParameter("name", new QName("String"), String.class,
                        ParameterMode.IN);
                call.addParameter("pwd", new QName("String"), String.class,
                        ParameterMode.IN);
                call.addParameter("cartContents", new QName("String[][]"),
                        String[][].class, ParameterMode.IN);
                call.setReturnType(new QName("Boolean"));
                result = (Boolean) (call.invoke("createAndCheckoutOrder",
                        params));

                if (!result.booleanValue()) {
                    JOptionPane
                            .showMessageDialog(
                                    frame,
                                    "Cart checkout could not complete.  \n"
                                            + "Please check your username and password and try again.",
                                    "Shopping cart error",
                                    JOptionPane.ERROR_MESSAGE);
                    return;
                }
                cartMainPanel.removeAllItems();
                JOptionPane.showMessageDialog(frame,
                        "Thank you for your order!", "Order has been sent",
                        JOptionPane.INFORMATION_MESSAGE);

            }
            ld.dispose();
        }
    }
}
