/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 * 
 **/
package org.activemq.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.activemq.message.ActiveMQMessage;
import org.activemq.message.ConsumerInfo;
import org.activemq.message.MessageAck;
import org.activemq.service.MessageContainerAdmin;
import org.activemq.service.MessageIdentity;
import org.activemq.service.Subscription;
import org.activemq.service.TopicMessageContainer;
import org.activemq.store.RecoveryListener;
import org.activemq.store.TopicMessageStore;

import javax.jms.JMSException;

/**
 * A default implemenation of a Durable Topic based
 * {@link org.activemq.service.MessageContainer}
 * which acts as an adapter between the {@link org.activemq.service.MessageContainerManager}
 * requirements and those of the persistent {@link TopicMessageStore} implementations.
 *
 * @version $Revision: 1.1.1.1 $
 */
public class DurableTopicMessageContainer implements TopicMessageContainer, MessageContainerAdmin {
    private static final Log log = LogFactory.getLog(DurableTopicMessageContainer.class);

    private TopicMessageStore messageStore;
    private String destinationName;
    private MessageIdentity lastMessageIdentity;

    public DurableTopicMessageContainer(TopicMessageStore messageStore, String destinationName) {
        this.messageStore = messageStore;
        this.destinationName = destinationName;
    }

    public String getDestinationName() {
        return destinationName;
    }

    public void addMessage(ActiveMQMessage message) throws JMSException {
        messageStore.addMessage(message);
        lastMessageIdentity = message.getJMSMessageIdentity();
    }

    public void delete(MessageIdentity messageID, MessageAck ack) throws JMSException {
        // only called in MessagePointer and so shouldn't really delete
        //messageStore.removeMessage(new MessageIdentity(messageID));
    }

    public boolean containsMessage(MessageIdentity messageIdentity) throws JMSException {
        /** TODO: make more optimal implementation */
        return getMessage(messageIdentity) != null;
    }

    public ActiveMQMessage getMessage(MessageIdentity messageID) throws JMSException {
        return messageStore.getMessage(messageID);
    }

    public void registerMessageInterest(MessageIdentity messageIdentity) throws JMSException {
        messageStore.incrementMessageCount(messageIdentity);
    }

    public void unregisterMessageInterest(MessageIdentity ack) throws JMSException {
        messageStore.decrementMessageCountAndMaybeDelete(ack);
    }


    public void setLastAcknowledgedMessageID(Subscription subscription, MessageIdentity messageIdentity) throws JMSException {
        messageStore.setLastAcknowledgedMessageIdentity(subscription.getPersistentKey(), messageIdentity);
    }

    public void recoverSubscription(final Subscription subscription) throws JMSException {
        messageStore.recoverSubscription(subscription.getPersistentKey(), lastMessageIdentity, new RecoveryListener() {
            public void recoverMessage(MessageIdentity messageIdentity) throws JMSException {
                subscription.addMessage(DurableTopicMessageContainer.this, getMessage(messageIdentity));
            }
        });
    }

    public void storeSubscription(ConsumerInfo info, Subscription subscription) throws JMSException {
        messageStore.setSubscriberEntry(info, subscription.getSubscriptionEntry());
    }

    public void start() throws JMSException {
        lastMessageIdentity = messageStore.getLastestMessageIdentity();
        messageStore.start();
    }

    public void stop() throws JMSException {
        messageStore.stop();
    }

    /**
     * @see org.activemq.service.MessageContainer#getMessageContainerAdmin()
     */
    public MessageContainerAdmin getMessageContainerAdmin() {
        return this;
    }

    /**
     * @see org.activemq.service.MessageContainerAdmin#empty()
     */
    public void empty() throws JMSException {
        messageStore.removeAllMessages();
    }

    /**
     * @see org.activemq.service.MessageContainer#isDeadLetterQueue()
     */
    public boolean isDeadLetterQueue() {
        return false;
    }

    public void deleteSubscription(String sub) throws JMSException {
        messageStore.deleteSubscription(sub);      
    }
}
