package vs;

import java.util.HashMap;

import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.Destination;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageConsumer;
import jakarta.jms.MessageListener;
import jakarta.jms.MessageProducer;
import jakarta.jms.Queue;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * replier for String reverter service, reuses MessageProducer objects for
 * temporary reply queues to requesters via replyProducers
 *
 * @author Sandro Leuchter
 *
 */
public class UmdreherReuseProducers implements MessageListener {
	private Connection connection;
	private Session session;
	private MessageConsumer consumer;
	private HashMap<Destination, MessageProducer> replyProducers = new HashMap<>();

	/**
	 * constructor, establishes and starts connection to JMS provider specified in
	 * JNDI (via jndi.properties), afterwards a consumer is ready
	 *
	 * @throws NamingException JNDI exceptions
	 * @throws JMSException    JMS exceptions
	 */
	public UmdreherReuseProducers() throws NamingException, JMSException {
		Context ctx = new InitialContext();
		ConnectionFactory factory = (ConnectionFactory) ctx.lookup("ConnectionFactory");
		Queue queue = (Queue) ctx.lookup(Conf.QUEUE);
		this.connection = factory.createConnection();
		this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		this.consumer = this.session.createConsumer(queue);
		this.consumer.setMessageListener(this);
		this.connection.start();
	}

	/**
	 * actual implementation of reverse service
	 *
	 * @param in String to reverse
	 * @return reverse of in
	 */
	public String revers(String in) {
		String out = "";
		for (char c : in.toCharArray()) {
			out = c + out;
		}
		return out;
	}

	/**
	 * asynchronous message consumption
	 *
	 * @see jakarta.jms.MessageListener
	 */
	@Override
	public void onMessage(Message request) {
		try {
			if (request instanceof TextMessage) {
				TextMessage requestText = (TextMessage) request;
				System.out.println("empfangen: " + requestText.getText());
				Destination replyQueue = request.getJMSReplyTo();
				MessageProducer replyProducer = null;
				if (this.replyProducers.containsKey(replyQueue)) {
					replyProducer = this.replyProducers.get(replyQueue);
					System.out.println("Producer wird wiederverwendet: " + replyQueue.toString());
				} else {
					replyProducer = this.session.createProducer(replyQueue);
					this.replyProducers.put(replyQueue, replyProducer);
					System.out.println("Producer wird neu erzeugt: " + replyQueue.toString());
				}
				TextMessage reply = this.session.createTextMessage();
				reply.setText(revers(requestText.getText()));
				replyProducer.send(reply);
				Thread.sleep(1000);
			}
		} catch (JMSException | InterruptedException e) {
			System.err.println(e);
		}

	}

	/**
	 * main routine and starting point of program
	 *
	 * @param args not used
	 */
	public static void main(String[] args) {
		UmdreherReuseProducers node = null;
		try {
			node = new UmdreherReuseProducers();
			while (true) {
				Thread.sleep(1000);
			}
		} catch (InterruptedException | NamingException | JMSException e) {
			System.err.println(e);
		} finally {
			try {
				if ((node != null) && (node.consumer != null)) {
					node.consumer.close();
				}
				if ((node != null) && (node.session != null)) {
					node.session.close();
				}
				if ((node != null) && (node.connection != null)) {
					node.connection.close();
				}
			} catch (JMSException e) {
				System.err.println(e);
			}
		}
	}
}
