/*
 * Copyright (c) 2004, 2005, ADAPT project partners (IST-2001-37126).
 *
 * PurchaseOrderBasicServiceBean.java
 */

package org.eu.adapt.demonstrator.bs.manufacturer;

import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
import javax.ejb.FinderException;
import javax.ejb.SessionContext;
import javax.ejb.SessionBean;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerPO_xsd.PurchOrdType;
import org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.ShipmentNoticeType;
import org.eu.adapt.demonstrator.eb.manufacturer.FinishedGoodsLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.InventoryItemLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.ItemLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.PurchaseOrderLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.CustomerLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.PurchaseOrderHomeLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.CustomerHomeLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.FinishedGoodsHomeLocal;
import org.eu.adapt.demonstrator.eb.manufacturer.ItemHomeLocal;
import org.eu.adapt.demonstrator.util.UniqueIdentifierGenerator;
import org.eu.adapt.services.demo_1_1.manufacturer.PurchaseOrderBasicService_wsdl.*;
import org.eu.adapt.services.demo_1_1.manufacturer.PurchaseOrderBasicService_wsdl.types.PurchaseOrderState;
import org.eu.adapt.services.demo_1_1.manufacturer.PurchaseOrderBasicService_wsdl.types.PurchaseOrderStatus;

public class PurchaseOrderBasicServiceBean implements SessionBean, PurchaseOrderBasicServicePortType
{
    public String[] listPurchaseOrders()
        throws RemoteException
    {
        String[] purchaseOrderNumbers = null;

        try
        {
            Collection purchaseOrders         = _purchaseOrderHome.findAll();
            Iterator   purchaseOrdersIterator = purchaseOrders.iterator();
            
            purchaseOrderNumbers = new String[purchaseOrders.size()];
            int index = 0;
            while (purchaseOrdersIterator.hasNext())
            {
                purchaseOrderNumbers[index] = ((PurchaseOrderLocal) purchaseOrdersIterator.next()).getOrderNumber();
                index++;
            }
        }
        catch (FinderException findException)
        {
            purchaseOrderNumbers = new String[0];
            System.out.println("Unable to find all purchase orders: \"" + findException + "\"");
        }
        catch (Exception exception)
        {
            purchaseOrderNumbers = new String[0];
            System.out.println("Exception: \"" + exception + "\"");
        }
        catch (Error error)
        {
            purchaseOrderNumbers = new String[0];
            System.out.println("Error: \"" + error + "\"");
        }

        return purchaseOrderNumbers;
    }

    public PurchaseOrderState getPurchaseOrderState(String purchaseOrderNumber)
        throws RemoteException
    {
        PurchaseOrderState state = new PurchaseOrderState();
        
        try
        {
            PurchaseOrderLocal purchaseOrder = _purchaseOrderHome.findByPrimaryKey(purchaseOrderNumber);
            
            state.setOrderNumber(purchaseOrder.getOrderNumber());
            state.setTotal(purchaseOrder.getTotal());
            
            CustomerLocal customer = purchaseOrder.getCustomer();
            if (customer != null)
                state.setCustomerReference(customer.getReference());
            else
                state.setCustomerReference(null);

            Collection items         = purchaseOrder.getItems();
            Iterator   itemsIterator = items.iterator();
            String[]   itemIDs       = new String[items.size()];
            int index = 0;
            while (itemsIterator.hasNext())
            {
                itemIDs[index] = ((ItemLocal) itemsIterator.next()).getId();
                index++;
            }
            state.setItemIDs(itemIDs);
        }
        catch (FinderException finderException)
        {
            System.out.println("Unable to find purchase order: \"" + purchaseOrderNumber + "\"");
        }
        catch (Exception exception)
        {
            System.out.println("PurchaseOrderBasicServiceBean.getPurchaseOrderState exception: \"" + exception + "\"");
            throw new RemoteException("PurchaseOrderBasicServiceBean.getPurchaseOrderState exception", exception);
        }
        catch (Error error)
        {
            System.out.println("PurchaseOrderBasicServiceBean.getPurchaseOrderState error: \"" + error + "\"");
            throw new RemoteException("PurchaseOrderBasicServiceBean.getPurchaseOrderState error", error);
        }

        return state;
    }

    public boolean checkPurchaseOrder(PurchOrdType purchOrd)
        throws RemoteException
    {
        boolean purchaseOrderIsValid = true;
        
        String customerRef = purchOrd.getCustomerRef();
        try
        {
            _customerHome.findByPrimaryKey(customerRef);
        }
        catch (FinderException finderException)
        {
            System.out.println("Unable to find customer: \"" + customerRef + "\"");
            purchaseOrderIsValid = false;
        }

        org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerPO_xsd.Item[] items = purchOrd.getItems().getItem();
        for (int index = 0; purchaseOrderIsValid && (index < items.length); index++)
        {
            String finishedGoodsName = items[index].getID().toString();
            try
            {
                purchaseOrderIsValid = _finishedGoodsHome.findByPrimaryKey(finishedGoodsName) != null;
            }
            catch (FinderException finderException)
            {
                System.out.println("Unable to find finished goods: \"" + finishedGoodsName + "\"");
                purchaseOrderIsValid = false;
            }
            
            purchaseOrderIsValid = purchaseOrderIsValid && (items[index].getQty() > 0);
        }

        return purchaseOrderIsValid;
    }

    public boolean addPurchaseOrder(PurchOrdType purchOrd)
        throws RemoteException
    {
        boolean worked      = true;
        String  customerRef = purchOrd.getCustomerRef();
        String  orderNumber = purchOrd.getOrderNum();
        float   total       = purchOrd.getTotal();
        org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerPO_xsd.Item[] items = purchOrd.getItems().getItem();
        try
        {
            CustomerLocal customer = _customerHome.findByPrimaryKey(customerRef);

            PurchaseOrderLocal purchaseOrder = _purchaseOrderHome.create(orderNumber, customer, total);
            
            for (int index = 0; index < items.length; index++)
            {
                String name     = items[index].getID().toString();
                int    quantity = items[index].getQty();
                float  price    = items[index].getPrice();

                FinishedGoodsLocal finishedGoods = _finishedGoodsHome.findByPrimaryKey(name);

                ItemLocal item = _itemHome.create(finishedGoods, quantity, price);

                purchaseOrder.getItems().add(item);
            }
        }
        catch (Exception exception)
        {
            worked = false;
            System.out.println("Exception: \"" + exception + "\"");
        }
        catch (Error error)
        {
            worked = false;
            System.out.println("Error: \"" + error + "\"");
        }

        return worked;
    }

    public PurchaseOrderStatus updatePurchaseOrder(String purchaseOrderNumber)
        throws RemoteException
    {
        PurchaseOrderStatus purchaseOrderStatus = PurchaseOrderStatus.UNKNOWN;

        try
        {
            PurchaseOrderLocal purchaseOrder = _purchaseOrderHome.findByPrimaryKey(purchaseOrderNumber);

            Collection items         = purchaseOrder.getItems();
            Iterator   itemsIterator = items.iterator();
            boolean allAllocated     = true;
            boolean allocationChange = false;
            while (itemsIterator.hasNext())
            {
                ItemLocal item = (ItemLocal) itemsIterator.next();

                if (item.getStorehouse() == null)
                {
                    FinishedGoodsLocal finishedGoods = item.getFinishedGoods();

                    Collection inventoryItems         = finishedGoods.getInventoryItems();
                    Iterator   inventoryItemsIterator = inventoryItems.iterator();
                    while (inventoryItemsIterator.hasNext())
                    {
                        InventoryItemLocal inventoryItem = (InventoryItemLocal) inventoryItemsIterator.next();

                        int neededAmount = item.getQuantity();
                        
                        if (inventoryItem.getAmountFree() >= neededAmount)
                        {
                            inventoryItem.setAmountFree(inventoryItem.getAmountFree() - neededAmount);
                            inventoryItem.setAmountAllocated(inventoryItem.getAmountAllocated() + neededAmount);
                            item.setStorehouse(inventoryItem.getStorehouse());
                            allocationChange = true;
                        }
                        else
                            allAllocated = false;
                    }
                }
            }

            if (allAllocated && (! allocationChange))
                purchaseOrderStatus = PurchaseOrderStatus.ALREADY_COMPLETE;
            else if (allAllocated && allocationChange)
                purchaseOrderStatus = PurchaseOrderStatus.NOW_COMPLETE;
            else
                purchaseOrderStatus = PurchaseOrderStatus.NOT_COMPLETE;
        }
        catch (Exception exception)
        {
            _sessionContext.setRollbackOnly();
            purchaseOrderStatus = PurchaseOrderStatus.UNKNOWN;
            System.out.println("Exception in updatePurchaseOrder: \"" + exception + "\"");
        }
        catch (Error error)
        {
            _sessionContext.setRollbackOnly();
            purchaseOrderStatus = PurchaseOrderStatus.UNKNOWN;
            System.out.println("Error in updatePurchaseOrder: \"" + error + "\"");
        }
        
        return purchaseOrderStatus;
    }

    public ShipmentNoticeType createShipmentNotice(String purchaseOrderNumber)
        throws RemoteException
    {
        ShipmentNoticeType shipmentNotice = new ShipmentNoticeType();
        
        try
        {
            PurchaseOrderLocal purchaseOrder = _purchaseOrderHome.findByPrimaryKey(purchaseOrderNumber);

            shipmentNotice.setOrderNum(purchaseOrderNumber);
//Causes Axis bug.
//          shipmentNotice.setCustomerRef(new CustomerReferenceType(customerReference)); 
            shipmentNotice.setShipNum(UniqueIdentifierGenerator.createUniqueIdentifier());

            Collection items         = purchaseOrder.getItems();
            Iterator   itemsIterator = items.iterator();
            org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.Item[] shipmentItems = new org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.Item[items.size()];
            int itemIndex = 0;
            while (itemsIterator.hasNext())
            {
                ItemLocal item = (ItemLocal) itemsIterator.next();

                shipmentItems[itemIndex] = new org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.Item();
                shipmentItems[itemIndex].setID(item.getFinishedGoods().getId());
                shipmentItems[itemIndex].setQty(item.getQuantity());
                shipmentItems[itemIndex].setPrice(item.getPrice());

                itemIndex++;
            }

            org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.ItemList shipmentItemList = new org.ws_i.www.SampleApplications.SupplyChainManagement._2002_10.ManufacturerSN_xsd.ItemList();
            shipmentItemList.setItem(shipmentItems);
            shipmentNotice.setItems(shipmentItemList);
        }
        catch (Exception exception)
        {
            System.out.println("Exception in createShipmentNotice: \"" + exception + "\"");
        }
        catch (Error error)
        {
            System.out.println("Error in createShipmentNotice: \"" + error + "\"");
        }
        
        return shipmentNotice;
    }

    public boolean removePurchaseOrder(PurchOrdType purchOrd)
        throws RemoteException
    {
        boolean worked      = true;
        String  orderNumber = purchOrd.getOrderNum();
        try
        {
            _purchaseOrderHome.remove(orderNumber);
        }
        catch (Exception exception)
        {
            worked = false;
            System.out.println("Exception: \"" + exception + "\"");
        }
        catch (Error error)
        {
            worked = false;
            System.out.println("Error: \"" + error + "\"");
        }

        return worked;
    }

    public void setSessionContext(SessionContext sessionContext)
    {
        _sessionContext = sessionContext;
    }

    public void unsetSessionContext()
    {
        _sessionContext = null;
    }

    public void ejbCreate()
    {
        try
        {
            InitialContext initialContext = new InitialContext();

//            _purchaseOrderHome = (PurchaseOrderHomeLocal) initialContext.lookup("java:comp/env/ejb/PurchaseOrderHomeLocal");
//            _customerHome      = (CustomerHomeLocal) initialContext.lookup("java:comp/env/ejb/CustomerHomeLocal");
//            _itemHome          = (ItemHomeLocal) initialContext.lookup("java:comp/env/ejb/ItemHomeLocal");
//            _finishedGoodsHome = (FinishedGoodsHomeLocal) initialContext.lookup("java:comp/env/ejb/FinishedGoodsHomeLocal");
            _purchaseOrderHome = (PurchaseOrderHomeLocal) initialContext.lookup("local/Manufacturer_PurchaseOrderEB");
            _customerHome      = (CustomerHomeLocal) initialContext.lookup("local/Manufacturer_CustomerEB");
            _itemHome          = (ItemHomeLocal) initialContext.lookup("local/Manufacturer_ItemEB");
            _finishedGoodsHome = (FinishedGoodsHomeLocal) initialContext.lookup("local/Manufacturer_FinishedGoodsEB");

            initialContext.close();
        }
        catch (NamingException namingException)
        {
            System.out.println("Name lookup problem: \"" + namingException + "\"");
            namingException.printStackTrace(System.out);
        }
        catch (Exception exception)
        {
            System.out.println("Problem: \"" + exception + "\"");
            exception.printStackTrace(System.out);
        }
        catch (Error error)
        {
            System.out.println("Problem: \"" + error + "\"");
            error.printStackTrace(System.out);
        }
    }

    public void ejbActivate()
    {
    }

    public void ejbPassivate()
    {
    }

    public void ejbLoad()
    {
    }

    public void ejbStore()
    {
    }    

    public void ejbRemove()
    {
        _purchaseOrderHome = null;
        _customerHome      = null;
        _itemHome          = null;
        _finishedGoodsHome = null;
    }

    private SessionContext _sessionContext = null;
    
    private transient PurchaseOrderHomeLocal _purchaseOrderHome = null;
    private transient CustomerHomeLocal      _customerHome      = null;
    private transient ItemHomeLocal          _itemHome          = null;
    private transient FinishedGoodsHomeLocal _finishedGoodsHome = null;
}
