package com.freedom.jms.samples;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import javax.jms.Connection;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.directory.InitialDirContext;

import com.ibm.jms.JMSBytesMessage;


public class JMSMDB implements MessageListener, ExceptionListener {
	
	
	static boolean tryToConnect = true;
	static int level = 2;
	

	static String cf = JMSValues.msgEng;
	static String readQueue = JMSValues.readQueue;
	
	QueueConnection connection=null; // Connect to it
	
	public static void main(java.lang.String[] args) {
		
		System.setProperty("javax.net.ssl.trustStore","/Users/mmik/Downloads/keystores/YOURACCOUNTID/cloudmq.jks");
	    System.setProperty("javax.net.ssl.keyStore","/Users/mmik/Downloads/keystores/YOURACCOUNTID/cloudmq.jks");
	    System.setProperty("javax.net.ssl.keyStorePassword","YOURACCOUNTPASSWORD");
	    System.setProperty("javax.net.ssl.trustStorePassword", "YOURACCOUNTPASSWORD");
	    long startTime;
	    long endTime;
		
		JMSMDB mdb = new JMSMDB();
		
		Connection c=null;

		try {
			for (int i=1;; i++) {
				println(4, "Start of loop "+i);
				if (tryToConnect) {
					try {
						tryToConnect = false;
						println(5, "======= Create MDB.");
						c = mdb.startListener("SUB_1", readQueue );
					} catch (JMSException je) {
						println(9, "Caught mdb: " + je);
						Exception e = je.getLinkedException();
						if (e!=null) println(5, "Linked Exception:" + e);
						tryToConnect = true;
					}
				}
				Thread.sleep(8000);
			}
		} catch (Exception e) {
			println(9, "Caught: " + e);
		}
	}
		
		
	Connection startListener(String subName, String readQueue) throws JMSException {
		
		
		//MQEnvironment.enableTracing(1);
		//===================================================
		// Name Space access
		String url = JMSValues.url;
		String icf = JMSValues.icf;

		java.util.Hashtable environment;
		InitialDirContext ctx = null;

		try {
			//===================================================
			// Get the Initial Context Factory from name space
			println(3, "======= Get Init Context Factory");
			environment = new java.util.Hashtable();
			environment.put(Context.INITIAL_CONTEXT_FACTORY, icf);
			environment.put(Context.PROVIDER_URL, url);
			environment.put(Context.REFERRAL, "throw");
			println(2, "icf "+icf);
			println(2, "url "+url);

			// Attempt to connect to the JNDI service provider, supplying
			// the properties previously supplied
			ctx = new InitialDirContext(environment);
			println(2, "JNDI Initial Context found (" + ctx + ")");
			
			

			//===================================================
			// Get the Connection Factory
			QueueConnectionFactory factory; // Get to product specific
			println(3, "======= Get Conn Factory for "+cf);
			try { // Attempt to retrieve a ConnectionFactory from JNDI namespace
				factory = (QueueConnectionFactory) ctx.lookup(cf);
			} catch (java.lang.Exception e) {
				println(2, "Did not find " + cf + " so trying " + cf);
				factory = (QueueConnectionFactory) ctx.lookup("cn=" + cf);
			}
			

			//===================================================
			// Create the connection and start it
			println(3, "======= Create connection");
			connection = factory.createQueueConnection();
			
			connection.start();
			connection.setExceptionListener(this);
			

			//===================================================
			// Create a session - each thread should have there own
			Session session; // Required per thread
			boolean transacted = false;
			int sflags = Session.AUTO_ACKNOWLEDGE;
			println(3, "======= Create session");
			session = connection.createSession(transacted, sflags);
			

			//===================================================
			// Look up destination definition from name space
			Queue  queue; // Look up destination definition from name space
			println(3, "======= Get destination from name space on "+readQueue);
			queue = (Queue) ctx.lookup("cn="+readQueue);
			

			//===================================================
			// Receiver the message
			
			MessageConsumer messageConsumer;
			
			println(3, "======= Receiver the message");
			// In Main program (possibly of some other class) 
			JMSMDB listener = new JMSMDB();
			messageConsumer = session.createConsumer(queue);
			
			messageConsumer.setMessageListener(listener);

		//===================================================
		// Catch any exceptions
		} catch (JMSException je) {
			println(9, "Caught1: " + je);
			Exception e = je.getLinkedException();
			if (e != null) {
				println(9, "linked exception: " + e);
			}
			try {
				Thread.sleep(10000);
			} catch (Exception ee) {}
			throw (je);
		} catch (Exception e) {
			println(9, "Caught2: " + e);
		}
		
		return (connection);
	}

	
	public void close(Connection connection) {
		try {
			println(3, "======= Close the connection "+connection);

			//===================================================
			// Clean up
			if (connection != null) {
				println(2, "Connection is open");
				connection.close();
			}
			println(3, "Clean up is complete");

		//	===================================================
		//	 Catch any exceptions
		} catch (JMSException je) {
			println(9, "Caught: " + je);
			Exception e = je.getLinkedException();
			if (e != null) {
				println(9, "linked exception: " + e);
			}
		} catch (Exception e) {
			println(9, "Caught: " + e);
		}
	}

	static void println(int l, String text) {
		if (l>=level) {
			String time = Utils.longToDateString(System.currentTimeMillis());
			System.out.println(time + " " + 
					Thread.currentThread().getName()+" \t"+text);
		}
	}

	public void onMessage(Message message) {
		try {
			
			println(4, "Message "+message.getJMSMessageID());
			
		
		} catch (Exception e) {
			println(9, "Caught: " + e);
		}
	}


	public void onException(JMSException je) {
		try {
			Exception e = je.getLinkedException();
			println(5, "======= Exception Caught:" + je);
			if (e!=null) println(5, "======= Linked Exception:" + e);
			println(5, "Sleep 10 seconds then try to reconnect" + je);
			Thread.sleep(10000);
			close(connection);
			tryToConnect = true;
		} catch (Exception e) {
			println(9, "Caught: " + e);
		}
	}
}
