package org.mockejb.jms;

import java.util.*;
import javax.jms.*;

/**
 * Destination where messages are sent.
 * Messages are kept in list, ordered by priority.
 * 
 * @author Dimitar Gospodinov
 */
abstract class MockDestination implements Destination {
    
    private String name;
    // Need to keep copy of each message in order to be able to test synchronous consumers
    private List messages = new ArrayList();
    // Consumers interested in this destination
    private List consumers = new ArrayList();

    /**
     * Creates new destination with name <code>name</code>
     * @param name
     */    
    MockDestination(String name) {
        this.name = name;
    }
    
    /**
     * Returns this destination's name.
     */
    public String getName() {
        return name;
    }
    
    /**
     * Adds message <code>msg</code> to this destination.
     * @param msg
     * @throws JMSException
     */
    void addMessage(Message msg) throws JMSException {

        MessageImpl sentMsg = MessageUtility.copyMessage(msg, true);
        
        int i = 0;
        while (i < messages.size()) {
                if (msg.getJMSPriority() > ((Message)messages.get(i)).getJMSPriority()) {
                    break;
                }
                i++;
        }
        messages.add(i, sentMsg);
        
        // Send message to all registered consumers
        Iterator it = consumers.iterator();
        while (it.hasNext()) {
            MockConsumer cons = (MockConsumer)it.next();
            cons.consume(sentMsg);
        }
    }
    
    /**
     * Removes all messages from this destination.
     *
     */
    public void clear() {
        messages.clear();
    }
    
    /**
     * Returns string representation of this destination.
     */
    public String toString() {
        return this.getClass().getName() + " with name: " + getName();
    }
    
    /**
     * Returns number of messages in this destination.
     */
    public int size() {
        return messages.size();
    }
    
    /**
     * Retrieves message at index <code>index</code>.
     * @param index
     */
    public Message getMessageAt(int index) {
        return (Message)messages.get(index);
    }
    
    /**
     * Retruns ordered <code>List</code> with all messages sent to
     * this destination. Higher priority messages appear first in the list.
     */
    public List getMessages() {
        return messages;
    }
  
    void registerConsumer(MockConsumer consumer)  throws JMSException {
         cleanConsumers();
         consumer.consume(messages);
         consumers.add(consumer);
    }

    void removeConsumer(MockConsumer consumer) {
        consumers.remove(consumer);
    }
    
    private void cleanConsumers() {
        ListIterator it = consumers.listIterator();
        while (it.hasNext()) {
            MockConsumer cons = (MockConsumer)it.next();
            if (cons.isClosed()) {
                it.remove();
            }
        }
    }
  
}