/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the
 * License at
 * http://www.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.net.messaging;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletContext;

/**
 * <p>
 *   The MessageSeparator class is a wrapper class that wraps around a
 *   MessageHandler. Its responsibility is to separate concatenated incoming
 *   messages before passing on the individual messages to the underlying
 *   MessageHandler.
 * </p>
 * <p>
 *   When adding a MessageHandler to a MessageServiceClient it automatically
 *   wraps a MessageSeparator around it before passing on the MessageSeparator
 *   to the underlying MessageServiceAdapter.
 * </p>
 *
 * @see        MessageHandler
 * @see        MessageServiceClient
 * @see        MessageServiceAdapter
 */
public class MessageSeparator
implements MessageHandler {
    private static final Logger LOGGER = Logger.getLogger(MessageSeparator.class.getName());

    private MessageHandler messageHandler;
    private ServletContext servletContext;

    public MessageSeparator(final MessageHandler messageHandler, final ServletContext servletContext) {
        this.messageHandler = messageHandler;
        this.servletContext = servletContext;
    }

    public void addCallback(final Callback callback) {
        // do nothing...
    }

    public void addCallback(final Callback callback, MessageSelector messageSelector) {
        // do nothing...
    }

    public MessageSelector getMessageSelector() {
        return messageHandler.getMessageSelector();
    }

    public void handle(final Message message) {
        if (message instanceof TextMessage && message.propertyExists(Message.MESSAGE_LENGTHS)) {
            TextMessage _textMessage = (TextMessage)message;
            StringTokenizer _lengths =
                new StringTokenizer(_textMessage.getStringProperty(Message.MESSAGE_LENGTHS), ",");
            int _beginIndex;
            int _endIndex = 0;
            while (_lengths.hasMoreTokens()) {
                _beginIndex = _endIndex;
                _endIndex = _beginIndex + Integer.parseInt(_lengths.nextToken());
                messageHandler.handle(subMessage(_textMessage, _beginIndex, _endIndex, servletContext));
            }
        } else if (message instanceof ObjectMessage && ((ObjectMessage)message).getObject() instanceof Serializable[]) {
            ObjectMessage _objectMessage = (ObjectMessage)message;
            Serializable[] _objects = (Serializable[])_objectMessage.getObject();
            for (final Serializable _object : _objects) {
                messageHandler.handle(subMessage(_objectMessage, _object, servletContext));
            }
        } else {
            messageHandler.handle(message);
        }
    }

    public void removeCallback(final Callback callback) {
        // do nothing...
    }

    public void setMessageSelector(final MessageSelector messageSelector) {
        messageHandler.setMessageSelector(messageSelector);
    }

    public String toString() {
        return messageHandler.toString();
    }

    private static ObjectMessage subMessage(
        final ObjectMessage objectMessage, final Serializable object, final ServletContext servletContext) {

        ObjectMessage _objectMessage =
            new ObjectMessage(object, servletContext);
        Enumeration _propertyNames = objectMessage.getPropertyNames();
        while (_propertyNames.hasMoreElements()) {
            String _propertyName = (String)_propertyNames.nextElement();
            _objectMessage.setObjectProperty(_propertyName, objectMessage.getObjectProperty(_propertyName));
        }
        return _objectMessage;
    }

    private static TextMessage subMessage(
        final TextMessage textMessage, final int beginIndex, final int endIndex, final ServletContext servletContext) {

        TextMessage _textMessage =
            new TextMessage(textMessage.getText().substring(beginIndex, endIndex), servletContext);
        Enumeration _propertyNames = textMessage.getPropertyNames();
        while (_propertyNames.hasMoreElements()) {
            String _propertyName = (String)_propertyNames.nextElement();
            if (!_propertyName.equalsIgnoreCase(Message.MESSAGE_LENGTHS)) {
                _textMessage.setObjectProperty(_propertyName, textMessage.getObjectProperty(_propertyName));
            }
        }
        return _textMessage;
    }
}
