/**
 * 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.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

/**
 * The handler that allows ItemPanel objects to be dragged to the shopping cart.
 */
class ItemPanelTransferHandler extends TransferHandler {

    /** The flavor for the transfer handler */
    private DataFlavor itemPanelFlavor;

    /** The type of the object that will be transferred. */
    private String itemPanelType = DataFlavor.javaJVMLocalObjectMimeType + ";class="
            + ItemPanel.class.getName();

    /**
     * Transfer handler to handle drag and drop of item panels.
     */
    public ItemPanelTransferHandler() {
        try {
            itemPanelFlavor = new DataFlavor(itemPanelType);
        } catch (ClassNotFoundException e) {
            System.out.println("ItemPanelTransferHandler: unable to create data flavor");
        }
    }

    /**
     * Handle the drop part of the drag&drop.
     * @param c the component on which the transferable is being dropped
     * @param t the object being dragged
     * @return true if the item can be imported into this component, false
     * otherwise
     */
    public boolean importData(JComponent c, Transferable t) {
        ItemPanel item;
        try {
            item = (ItemPanel) t.getTransferData(itemPanelFlavor);
            addItemToCart(c, item.getItem());
        } catch (UnsupportedFlavorException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        c.validate();
        c.repaint();
        return true;
    }

    /**
     * Create transferable out of the ItemPanel component.
     * @see javax.swing.TransferHandler#createTransferable(javax.swing.JComponent)
     */
    protected Transferable createTransferable(JComponent c) {
        ItemPanel panel = (ItemPanel) c;
        return new ItemPanelTransferable(panel);
    }

    /**
     * Get the supported actions for the drag and drop.
     * @see javax.swing.TransferHandler#getSourceActions(javax.swing.JComponent)
     */
    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    /**
     * @see javax.swing.TransferHandler#exportDone(javax.swing.JComponent, java.awt.datatransfer.Transferable, int)
     */
    protected void exportDone(JComponent c, Transferable data, int action) {
    }

    /**
     * Determine whether the given component can accept the given data flavors.
     * @param c the component that potentially takes an import
     * @param flavors the list of flavors that describes the importable data
     * @see javax.swing.TransferHandler#canImport(javax.swing.JComponent, java.awt.datatransfer.DataFlavor[])
     * @return true if the component can import the given data flavor, false
     * otherwise
     */
    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        // do not allow to drop on the ItemPanel area of the client (because it
        // uses the same TransferHandler and will try to import data)
        if (c instanceof ItemPanel) {
            return false;
        }

        for (int i = 0; i < flavors.length; i++) {
            if (itemPanelFlavor.equals(flavors[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Add item to the shopping cart.
     * @param c the shopping cart panel on which the item is being dropped.
     * @param item the item that needs to be added to the cart.
     */
    private void addItemToCart(JComponent c, Item item) {
        ShoppingCartPanel cart = (ShoppingCartPanel) c;

        List items = cart.getItemsInCart();
        Iterator iter = items.iterator();

        OrderItem orderItem = new OrderItem(item);

        // item of this type is already in the cart, increase the quantity
        if (cart.isItemInCart(orderItem)) {
            cart.increaseQuantity(orderItem);
            return;
        }

        // this item was not found in the cart, so we add a new entry
        cart.addNewItemToCart(orderItem);
    }

    /**
     * A wrapper class for the panel that is being transferred from one component
     * to another using drag and drop.
     */
    class ItemPanelTransferable implements Transferable {

        /** The panel that is being dragged. */
        private ItemPanel panel;

        /**
         * Wrapper for the ItemPanel for transfer.
         * @param itemPanel the panel that is being wrapped for transfer
         */
        public ItemPanelTransferable(ItemPanel itemPanel) {
            panel = itemPanel;
        }

        /**
         * Get the data that is being transferred.
         * @param flavor the flavor of the data requested
         * @throws UnsupportedFlavorException if the flavor is not supported by
         * this handler
         * @return the ItemPanel cast as an Object
         */
        public Object getTransferData(DataFlavor flavor)
                throws UnsupportedFlavorException {
            if (!isDataFlavorSupported(flavor)) {
                throw new UnsupportedFlavorException(flavor);
            }
            return panel;
        }

        /**
         * Get the supported data flavors.
         * @return the array of data flavors supported by this handler.
         */
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[] {itemPanelFlavor};
        }

        /**
         * Is the given data flavor supported by this handler.
         * @param flavor the data flavor to check
         * @return true if the data flavor is supported, false otherwise
         */
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return itemPanelFlavor.equals(flavor);
        }
    }
}
