import java.io.*;
import javax.jms.*;
import javax.naming.*;

public class CoffeeMaker implements Runnable
{
	/** The machine that makes the coffee - think of it as a real world coffee machine (hardware). */
	protected CoffeeMachine machine;

	/** The JMS Connection to the Queue. */
	protected QueueConnection connection;
	
	/** The Queue to get orders from. */	
	protected Queue queue;
	
	/** The Session used to interract with the Queue. */
	protected QueueSession session;

	public static void main(String[] args)
	{
		try
		{
			QueueConnectionFactory factory = (QueueConnectionFactory)new InitialContext().lookup("java:comp/env/jms/theQueueConnectionFactory");
			
			QueueConnection connection = factory.createQueueConnection();

			Queue queue = (Queue)new InitialContext().lookup("java:comp/env/jms/theQueue");
			
			if(args.length > 0 && args[0].equals("-order"))
			{
				// Start the connection so we can use it
				connection.start();

				// Get the brand from the user
				BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
				System.out.print("Brand? ");
				String brand = reader.readLine();

				QueueSession session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
				
				// Create the request message, a plain Message will do since
				// we're just using the properties
				Message message = session.createMessage();
				
				// Specify the brand to brew
				message.setStringProperty("brand", brand);
				
				// We dont want it if it's not starting to brew within three minutes
				message.setJMSExpiration(180000);
				
				// Send our request
				session.createSender(queue).send(message);
				
				// Close up
				session.close();
				connection.close();
				
				System.out.println("Coffee order sent");
			}
			else
			{
				CoffeeMaker maker = new CoffeeMaker(connection, queue);
				maker.run();
			}
		}
		catch(JMSException e)
		{
			System.err.println("Communication error: " + e.getMessage());
		}
		catch(NamingException e)
		{
			System.err.println("Error looking up objects: " + e.getMessage());
		}
		catch(IOException e)
		{
			System.err.println("IO error: " + e.getMessage());
		}
	}

	/**
	 * Creates a new CoffeeMaker with the specified connection and queue.
	 */
	public CoffeeMaker(QueueConnection connection, Queue queue) throws JMSException
	{
		this.machine = new CoffeeMachine();

		this.connection = connection;
		this.queue = queue;
		this.session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
	}

	public void run()
	{
		try
		{
			// Start the connection so we can use it
			connection.start();
			
			// Create our receiver
			QueueReceiver receiver = session.createReceiver(queue);

			System.out.println("Waiting to receive coffee requests");

			while(true)
			{
				// Wait for a request for coffee
				Message message = receiver.receive();

				// Make a cup of the specified brand
				machine.makeCoffee(message.getStringProperty("brand"));
			}
		}
		catch(JMSException e)
		{
			System.err.println("Communication error: " + e.getMessage());
		}
	}
}
