/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package org.ocelotds.web;

import org.ocelotds.core.SessionManager;
import org.ocelotds.messaging.MessageEvent;
import org.ocelotds.messaging.MessageToClient;
import org.ocelotds.messaging.MessageType;
import java.util.ArrayList;
import java.util.Collection;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.EventMetadata;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;
import javax.websocket.Session;
import org.ocelotds.annotations.JsTopicEvent;
import org.ocelotds.annotations.OcelotLogger;
import org.ocelotds.marshalling.annotations.JsonMarshaller;
import org.slf4j.Logger;

/**
 * Bean that send push messages
 *
 * @author hhfrancois
 */
public class TopicsMessagesBroadcaster {

	@Inject
	@OcelotLogger
	private Logger logger;

	@Inject
	private SessionManager sessionManager;

	/**
	 * Send message to topic
	 *
	 * @param object
	 * @param metadata
	 */
	public void sendObjectToTopic(@Observes @JsTopicEvent("") Object object, EventMetadata metadata) {
		MessageToClient msg = new MessageToClient();
		InjectionPoint injectionPoint = metadata.getInjectionPoint();
		Annotated annotated = injectionPoint.getAnnotated();
		JsTopicEvent jte = annotated.getAnnotation(JsTopicEvent.class);
		if (jte != null) {
			msg.setId(jte.value());
			if (annotated.isAnnotationPresent(JsonMarshaller.class)) {
				msg.setJson(getJsonFromMarshaller(object, annotated.getAnnotation(JsonMarshaller.class)));
			} else {
				msg.setResponse(object);
			}
			sendMessageToTopic(msg);
		}
	}
	
	String getJsonFromMarshaller(Object object, JsonMarshaller jma) {
		Class<? extends org.ocelotds.marshalling.IJsonMarshaller> marshallerCls = jma.value();
		try {
			org.ocelotds.marshalling.IJsonMarshaller marshaller = marshallerCls.newInstance();
			return marshaller.toJson(object);
		} catch (InstantiationException | IllegalAccessException ex) {
			logger.error(marshallerCls+" can't be instantiate", ex);
		} catch (Throwable ex) {
			logger.error(object+" can't be serialized with marshaller "+marshallerCls, ex);
		}
		return null;
	}

	public int sendMessageToTopic(@Observes @MessageEvent MessageToClient msg) {
		msg.setType(MessageType.MESSAGE);
		int sended = 0;
		logger.debug("Sending message to topic {}...", msg);
		Collection<Session> sessions = sessionManager.getSessionsForTopic(msg.getId());
		if (sessions != null && !sessions.isEmpty()) {
			Collection<Session> sessionsClosed = new ArrayList<>();
			for (Session session : sessions) {
				if (session != null) {
					if (session.isOpen()) {
						session.getAsyncRemote().sendObject(msg);
						sended++;
					} else {
						sessionsClosed.add(session);
					}
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Send message to '{}' topic {} client(s) : {}", new Object[]{msg.getId(), sessions.size() - sessionsClosed.size(), msg});
			}
			if (!sessionsClosed.isEmpty()) {
				logger.debug("Session closed to remove '{}'", sessionsClosed.size());
				sessionManager.removeSessionsToTopic(sessionsClosed);
			}
		} else {
			logger.debug("No client for topic '{}'", msg.getId());
		}
		return sended;
	}
}

@@ -813,24 +813,77 @@
 lotLogger;%0D%0A
+import org.ocelotds.core.services.ArgumentServices;%0D%0A
 import org.o
@@ -1179,16 +1179,73 @@
 ger;%0D%0A%0D%0A
+%09@Inject%0D%0A%09private ArgumentServices argumentServices;%0D%0A%0D%0A
 %09/**%0D%0A%09 
@@ -1686,141 +1686,27 @@
 %0A%09%09%09
-msg.setId(jte.value());%0D%0A%09%09%09if (annotated.isAnnotationPresent(JsonMarshaller.class)) %7B%0D%0A%09%09%09%09msg.setJson(getJsonFromMarshaller(object,
+JsonMarshaller jm =
  ann
@@ -1751,22 +1751,17 @@
 ass)
-))
 ;%0D%0A%09%09%09
-%7D else
+try
  %7B%0D%0A
@@ -1775,366 +1775,217 @@
 .set
-Response(object);%0D%0A%09%09%09%7D%0D%0A%09%09%09sendMessageToTopic(msg);%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%09%0D%0A%09String getJsonFromMarshaller(Object object, JsonMarshaller jma) %7B%0D%0A%09%09Class%3C? extends org.ocelotds.marshalling.IJsonMarshaller%3E marshallerCls = jma.value(
+Id(jte.value());%0D%0A%09%09%09%09if (jm != null) %7B%0D%0A%09%09%09%09%09msg.setJson(argumentServices.getJsonResultFromSpecificMarshaller(jm, object)
 );%0D%0A%09%09
+%09
-try %7B%0D%0A%09%09%09org.ocelotds.marshalling.IJsonMarshaller marshaller = marshallerCls.newInstance(
+%09%7D else %7B%0D%0A%09%09%09%09%09msg.setResponse(object
 );%0D%0A%09%09%09
+%09
-return marshaller.toJson(object
+%7D%0D%0A%09%09%09%09sendMessageToTopic(msg
 );%0D%0A
+%09
 %09%09%7D 
@@ -2041,32 +2041,33 @@
 ption ex) %7B%0D%0A%09%09%09
+%09
 logger.error(mar
@@ -2063,29 +2063,18 @@
 r.error(
+j
 m
-arshallerCls
 +%22 can't
@@ -2099,16 +2099,17 @@
 ex);%0D%0A%09%09
+%09
 %7D catch 
@@ -2122,24 +2122,25 @@
 able ex) %7B%0D%0A
+%09
 %09%09%09logger.er
@@ -2194,21 +2194,10 @@
 r %22+
+j
 m
-arshallerCls
 , ex
@@ -2206,31 +2206,22 @@
 %0D%0A%09%09
+%09
 %7D%0D%0A%09%09
-return null;
+%7D
 %0D%0A%09%7D%0D%0A
+%09
 %0D%0A%09p

use argumentService for get Result