package jwsunleashed.trading;

import java.util.*;
import javax.naming.*;
import java.rmi.*;
import javax.rmi.*;
import javax.ejb.*;
import java.security.*;
import java.math.*;
import jwsunleashed.trading.ejb.*;

public class StockTrading
{
// The table of user sessions
    protected static Hashtable users = new Hashtable();
    protected SecureRandom random;

    public StockTrading()
    {
        try
        {
// Create the object for creating random session ID's
            random = SecureRandom.getInstance("SHA1PRNG");
        }
        catch (NoSuchAlgorithmException exc)
        {
            exc.printStackTrace();
        }
    }

    public String login(String userID, String password)
        throws TradingException
    {
        try
        {
            Context context = new InitialContext();

// Locate the Trading session home interface
            TradingHome home = (TradingHome) PortableRemoteObject.narrow(
                context.lookup("ejb/TradingHome"), TradingHome.class);

// Create a new trading session
            Trading trading = home.create(userID, password);

            byte[] uniqueID = new byte[16];

// Generate a random 128-bit (16-byte) session key
            random.nextBytes(uniqueID);

// Use BigInteger to create a string of hex digits
            String uniqueIDKey = (new BigInteger(uniqueID)).toString(16);

// Associate the key with the trading session
            users.put(uniqueIDKey, trading);

// Return the key to the user
            return uniqueIDKey;
        }
        catch (NamingException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
        catch (CreateException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
        catch (Exception exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult put(String uniqueID, String stock, int shares,
        int price)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Let the trading session handle the put request
            return trading.put(stock, shares, price);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult buy(String uniqueID, String stock, int shares,
        int price)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Let the trading session handle the buy request
            return trading.buy(stock, shares, price);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult retractPut(String uniqueID, int putID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Let the trading session retract the put request
            return trading.retractPut(putID);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult retractBuy(String uniqueID, int buyID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Let the trading session retract the buy request
            return trading.retractBuy(buyID);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult getPutStatus(String uniqueID, int putID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Fetch the put status from the session bean
            return trading.getPutStatus(putID);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult getBuyStatus(String uniqueID, int buyID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Fetch the buy status from the session bean
            return trading.getBuyStatus(buyID);
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult[] getOutstandingPuts(String uniqueID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Fetch the outstanding puts from the session bean
            return trading.getOutstandingPuts();
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public TradeResult[] getOutstandingBuys(String uniqueID)
        throws TradingException
    {
// Locate the user's session
        Trading trading = getTradingSession(uniqueID);

        try
        {
// Fetch the outstanding buys from the session bean
            return trading.getOutstandingBuys();
        }
        catch (RemoteException exc)
        {
            exc.printStackTrace();
            throw new TradingException(exc.toString());
        }
    }

    public void logout(String uniqueID)
        throws TradingException
    {
// Log the user out (remove the session)
        Trading trading = (Trading) users.get(uniqueID);
        if (trading != null)
        {
// Remove the session from the table
            users.remove(uniqueID);
            try
            {
// Remove the EJB session
                trading.remove();
            }
            catch (RemoveException exc)
            {
                exc.printStackTrace();
            }
            catch (RemoteException exc)
            {
                exc.printStackTrace();
            }

            return;
        }
        throw new TradingException("ID "+uniqueID+" is not logged in");
    }

    protected Trading getTradingSession(String uniqueID)
        throws TradingException
    {
        Trading trading = (Trading) users.get(uniqueID);

        if (trading != null) return trading;

        throw new TradingException("ID "+uniqueID+" is not logged in");
    }
}
