package jp.co.denso.fa.jmscaosql.util;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import jp.co.denso.fa.jcaosql.CaoSQLItem;
import jp.co.denso.fa.jcaosql.CaoSQLMessage;
import jp.co.denso.fa.jmscaosql.model.CaoSQLItemModel;
import jp.co.denso.fa.jmscaosql.model.CaoSQLMessageModel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * JMSメッセージの変換処理を行うクラスです。
 *
 * @author DENSO WAVE
 * @version 1.00
 */
public class JmsCaoSQLMessageConverter implements MessageConverter {

	/**
	 * ロガー
	 */
	private static Logger logger = LoggerFactory.getLogger(JmsCaoSQLMessageConverter.class);

	/**
	 * オブジェクトマッパー
	 */
	private final static ObjectMapper mapper = new ObjectMapper();

	/**
	 * JMSサーバから受け取ったメッセージをオブジェクトに変換します。
	 */
	public Object fromMessage(Message msg) throws JMSException, MessageConversionException {
		// NOP
		return null;
	}

	/**
	 * {@link Object}を{@link Message}に変換します。<br>
	 * サポートするObjectのサブクラスは{@link CaoSQLItem},{@link CaoSQLMessage},{@link String}です。<br>
	 * それ以外のサブクラスは空の{@link Message}として返却します。
	 *
	 * @param object メッセージ内容に設定するオブジェクト
	 * @param session JMSセッション
	 * @return JMSメッセージ
	 * @throws JMSException
	 * @throws MessageConversionException
	 */
	public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {

		logger.debug("start toMessage method. " + object.toString());
		TextMessage retMsg = session.createTextMessage();

		// 任意のオブジェクトをJMSメッセージオブジェクトに変換する処理を実装する
		if (object instanceof CaoSQLItem) {
			CaoSQLItemModel item = new CaoSQLItemModel((CaoSQLItem) object);
			String json = getJsonString(item);
			logger.debug(json);
			retMsg.setText(json);

		} else if (object instanceof jp.co.denso.fa.jcaosql.rmi.CaoSQLItem) {
			CaoSQLItemModel item = new CaoSQLItemModel((jp.co.denso.fa.jcaosql.rmi.CaoSQLItem) object);
			String json = getJsonString(item);
			logger.debug(json);
			retMsg.setText(json);
		} else if (object instanceof CaoSQLMessage) {
			CaoSQLMessageModel msg = new CaoSQLMessageModel((CaoSQLMessage) object);
			String json = getJsonString(msg);
			retMsg.setText(json);

		} else if (object instanceof jp.co.denso.fa.jcaosql.rmi.CaoSQLMessage) {
			CaoSQLMessageModel msg = new CaoSQLMessageModel((jp.co.denso.fa.jcaosql.rmi.CaoSQLMessage) object);
			String json = getJsonString(msg);
			retMsg.setText(json);

		} else if (object instanceof String) {
			retMsg.setText(object.toString());
		} else {
			// 上記以外の場合は、何も設定しないでおく
			retMsg.setText(null);
		}
		logger.debug("end toMessage method.");

		return retMsg;
	}

	/**
	 * int値を{@link Message}に変換します。<br>
	 *
	 * @param value メッセージ内容に設定するint値
	 * @param session JMSセッション
	 * @return JMSメッセージ
	 * @throws JMSException
	 * @throws MessageConversionException
	 */
	public Message toMessage(int value, Session session) throws JMSException, MessageConversionException {
		TextMessage retMsg = session.createTextMessage();
		retMsg.setText(Integer.toString(value));
		return retMsg;
	}

	/**
	 * long値を{@link Message}に変換します。<br>
	 *
	 * @param value メッセージ内容に設定するlong値
	 * @param session JMSセッション
	 * @return JMSメッセージ
	 * @throws JMSException
	 * @throws MessageConversionException
	 */
	public Message toMessage(long value, Session session) throws JMSException, MessageConversionException {
		TextMessage retMsg = session.createTextMessage();
		retMsg.setText(Long.toString(value));
		return retMsg;
	}

	/**
	 * double値を{@link Message}に変換します。<br>
	 *
	 * @param value メッセージ内容に設定するdouble値
	 * @param session JMSセッション
	 * @return JMSメッセージ
	 * @throws JMSException
	 * @throws MessageConversionException
	 */
	public Message toMessage(double value, Session session) throws JMSException, MessageConversionException {
		TextMessage retMsg = session.createTextMessage();
		retMsg.setText(Double.toString(value));
		return retMsg;
	}

	/**
	 * JSON文字列取得
	 *
	 * @param obj JSON変換対象のオブジェクト
	 * @return JSON文字列
	 */
	private static String getJsonString(Object obj) {
		try {
			// Null項目をJSONへ出力したくないような場合は、objectmapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
			return mapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			logger.error("", e);
		}

		return null;
	}
}
