/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
 * Copyright 2003-2007 Jive Software.
 *
 * All rights reserved. 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.jivesoftware.smackx;

import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.DiscoverItems;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * The OfflineMessageManager helps manage offline messages even before the user has sent an
 * available presence. When a user asks for his offline messages before sending an available
 * presence then the server will not send a flood with all the offline messages when the user
 * becomes online. The server will not send a flood with all the offline messages to the session
 * that made the offline messages request or to any other session used by the user that becomes
 * online.<p>
 *
 * Once the session that made the offline messages request has been closed and the user becomes
 * offline in all the resources then the server will resume storing the messages offline and will
 * send all the offline messages to the user when he becomes online. Therefore, the server will
 * flood the user when he becomes online unless the user uses this class to manage his offline
 * messages.
 *
 * @author Gaston Dombiak
 */
public class OfflineMessageManager {

    private final static String namespace = "http://jabber.org/protocol/offline";

    private Connection connection;

    private PacketFilter packetFilter;

    public OfflineMessageManager(Connection connection) {
        this.connection = connection;
        packetFilter =
                new AndFilter(new PacketExtensionFilter("offline", namespace),
                        new PacketTypeFilter(Message.class));
    }

    /**
     * Returns true if the server supports Flexible Offline Message Retrieval. When the server
     * supports Flexible Offline Message Retrieval it is possible to get the header of the offline
     * messages, get specific messages, delete specific messages, etc.
     *
     * @return a boolean indicating if the server supports Flexible Offline Message Retrieval.
     * @throws XMPPException If the user is not allowed to make this request.
     */
    public boolean supportsFlexibleRetrieval() throws XMPPException {
        DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(connection.getServiceName());
        return info.containsFeature(namespace);
    }

    /**
     * Returns the number of offline messages for the user of the connection.
     *
     * @return the number of offline messages for the user of the connection.
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public int getMessageCount() throws XMPPException {
        DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null,
                namespace);
        Form extendedInfo = Form.getFormFrom(info);
        if (extendedInfo != null) {
            String value = extendedInfo.getField("number_of_messages").getValues().next();
            return Integer.parseInt(value);
        }
        return 0;
    }

    /**
     * Returns an iterator on <tt>OfflineMessageHeader</tt> that keep information about the
     * offline message. The OfflineMessageHeader includes a stamp that could be used to retrieve
     * the complete message or delete the specific message.
     *
     * @return an iterator on <tt>OfflineMessageHeader</tt> that keep information about the offline
     *         message.
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public Iterator<OfflineMessageHeader> getHeaders() throws XMPPException {
        List<OfflineMessageHeader> answer = new ArrayList<OfflineMessageHeader>();
        DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection).discoverItems(
                null, namespace);
        for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) {
            DiscoverItems.Item item = it.next();
            answer.add(new OfflineMessageHeader(item));
        }
        return answer.iterator();
    }

    /**
     * Returns an Iterator with the offline <tt>Messages</tt> whose stamp matches the specified
     * request. The request will include the list of stamps that uniquely identifies
     * the offline messages to retrieve. The returned offline messages will not be deleted
     * from the server. Use {@link #deleteMessages(java.util.List)} to delete the messages.
     *
     * @param nodes the list of stamps that uniquely identifies offline message.
     * @return an Iterator with the offline <tt>Messages</tt> that were received as part of
     *         this request.
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public Iterator<Message> getMessages(final List<String> nodes) throws XMPPException {
        List<Message> messages = new ArrayList<Message>();
        OfflineMessageRequest request = new OfflineMessageRequest();
        for (String node : nodes) {
            OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
            item.setAction("view");
            request.addItem(item);
        }
        // Filter packets looking for an answer from the server.
        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
        PacketCollector response = connection.createPacketCollector(responseFilter);
        // Filter offline messages that were requested by this request
        PacketFilter messageFilter = new AndFilter(packetFilter, new PacketFilter() {
            public boolean accept(Packet packet) {
                OfflineMessageInfo info = (OfflineMessageInfo) packet.getExtension("offline",
                        namespace);
                return nodes.contains(info.getNode());
            }
        });
        PacketCollector messageCollector = connection.createPacketCollector(messageFilter);
        // Send the retrieval request to the server.
        connection.sendPacket(request);
        // Wait up to a certain number of seconds for a reply.
        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
        // Stop queuing results
        response.cancel();

        if (answer == null) {
            throw new XMPPException("No response from server.");
        } else if (answer.getError() != null) {
            throw new XMPPException(answer.getError());
        }

        // Collect the received offline messages
        Message message = (Message) messageCollector.nextResult(
                SmackConfiguration.getPacketReplyTimeout());
        while (message != null) {
            messages.add(message);
            message =
                    (Message) messageCollector.nextResult(
                            SmackConfiguration.getPacketReplyTimeout());
        }
        // Stop queuing offline messages
        messageCollector.cancel();
        return messages.iterator();
    }

    /**
     * Returns an Iterator with all the offline <tt>Messages</tt> of the user. The returned offline
     * messages will not be deleted from the server. Use {@link #deleteMessages(java.util.List)}
     * to delete the messages.
     *
     * @return an Iterator with all the offline <tt>Messages</tt> of the user.
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public Iterator<Message> getMessages() throws XMPPException {
        List<Message> messages = new ArrayList<Message>();
        OfflineMessageRequest request = new OfflineMessageRequest();
        request.setFetch(true);
        // Filter packets looking for an answer from the server.
        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
        PacketCollector response = connection.createPacketCollector(responseFilter);
        // Filter offline messages that were requested by this request
        PacketCollector messageCollector = connection.createPacketCollector(packetFilter);
        // Send the retrieval request to the server.
        connection.sendPacket(request);
        // Wait up to a certain number of seconds for a reply.
        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
        // Stop queuing results
        response.cancel();

        if (answer == null) {
            throw new XMPPException("No response from server.");
        } else if (answer.getError() != null) {
            throw new XMPPException(answer.getError());
        }

        // Collect the received offline messages
        Message message = (Message) messageCollector.nextResult(
                SmackConfiguration.getPacketReplyTimeout());
        while (message != null) {
            messages.add(message);
            message =
                    (Message) messageCollector.nextResult(
                            SmackConfiguration.getPacketReplyTimeout());
        }
        // Stop queuing offline messages
        messageCollector.cancel();
        return messages.iterator();
    }

    /**
     * Deletes the specified list of offline messages. The request will include the list of
     * stamps that uniquely identifies the offline messages to delete.
     *
     * @param nodes the list of stamps that uniquely identifies offline message.
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public void deleteMessages(List<String> nodes) throws XMPPException {
        OfflineMessageRequest request = new OfflineMessageRequest();
        for (String node : nodes) {
            OfflineMessageRequest.Item item = new OfflineMessageRequest.Item(node);
            item.setAction("remove");
            request.addItem(item);
        }
        // Filter packets looking for an answer from the server.
        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
        PacketCollector response = connection.createPacketCollector(responseFilter);
        // Send the deletion request to the server.
        connection.sendPacket(request);
        // Wait up to a certain number of seconds for a reply.
        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
        // Stop queuing results
        response.cancel();

        if (answer == null) {
            throw new XMPPException("No response from server.");
        } else if (answer.getError() != null) {
            throw new XMPPException(answer.getError());
        }
    }

    /**
     * Deletes all offline messages of the user.
     *
     * @throws XMPPException If the user is not allowed to make this request or the server does
     *                       not support offline message retrieval.
     */
    public void deleteMessages() throws XMPPException {
        OfflineMessageRequest request = new OfflineMessageRequest();
        request.setPurge(true);
        // Filter packets looking for an answer from the server.
        PacketFilter responseFilter = new PacketIDFilter(request.getPacketID());
        PacketCollector response = connection.createPacketCollector(responseFilter);
        // Send the deletion request to the server.
        connection.sendPacket(request);
        // Wait up to a certain number of seconds for a reply.
        IQ answer = (IQ) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
        // Stop queuing results
        response.cancel();

        if (answer == null) {
            throw new XMPPException("No response from server.");
        } else if (answer.getError() != null) {
            throw new XMPPException(answer.getError());
        }
    }
}
