/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
 * Copyright 2003-2006 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.Connection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.Cache;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.DiscoverItems;
import org.jivesoftware.smackx.packet.MultipleAddresses;

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

/**
 * A MultipleRecipientManager allows to send packets to multiple recipients by making use of
 * <a href="http://www.jabber.org/jeps/jep-0033.html">JEP-33: Extended Stanza Addressing</a>.
 * It also allows to send replies to packets that were sent to multiple recipients.
 *
 * @author Gaston Dombiak
 */
public class MultipleRecipientManager {

    /**
     * Create a cache to hold the 100 most recently accessed elements for a period of
     * 24 hours.
     */
    private static Cache<String, String> services = new Cache<String, String>(100, 24 * 60 * 60 * 1000);

    /**
     * Sends the specified packet to the list of specified recipients using the
     * specified connection. If the server has support for JEP-33 then only one
     * packet is going to be sent to the server with the multiple recipient instructions.
     * However, if JEP-33 is not supported by the server then the client is going to send
     * the packet to each recipient.
     *
     * @param connection the connection to use to send the packet.
     * @param packet     the packet to send to the list of recipients.
     * @param to         the list of JIDs to include in the TO list or <tt>null</tt> if no TO
     *                   list exists.
     * @param cc         the list of JIDs to include in the CC list or <tt>null</tt> if no CC
     *                   list exists.
     * @param bcc        the list of JIDs to include in the BCC list or <tt>null</tt> if no BCC
     *                   list exists.
     * @throws XMPPException if server does not support JEP-33: Extended Stanza Addressing and
     *                       some JEP-33 specific features were requested.
     */
    public static void send(Connection connection, Packet packet, List<String> to, List<String> cc, List<String> bcc)
            throws XMPPException {
        send(connection, packet, to, cc, bcc, null, null, false);
    }

    /**
     * Sends the specified packet to the list of specified recipients using the
     * specified connection. If the server has support for JEP-33 then only one
     * packet is going to be sent to the server with the multiple recipient instructions.
     * However, if JEP-33 is not supported by the server then the client is going to send
     * the packet to each recipient.
     *
     * @param connection the connection to use to send the packet.
     * @param packet     the packet to send to the list of recipients.
     * @param to         the list of JIDs to include in the TO list or <tt>null</tt> if no TO
     *                   list exists.
     * @param cc         the list of JIDs to include in the CC list or <tt>null</tt> if no CC
     *                   list exists.
     * @param bcc        the list of JIDs to include in the BCC list or <tt>null</tt> if no BCC
     *                   list exists.
     * @param replyTo    address to which all replies are requested to be sent or <tt>null</tt>
     *                   indicating that they can reply to any address.
     * @param replyRoom  JID of a MUC room to which responses should be sent or <tt>null</tt>
     *                   indicating that they can reply to any address.
     * @param noReply    true means that receivers should not reply to the message.
     * @throws XMPPException if server does not support JEP-33: Extended Stanza Addressing and
     *                       some JEP-33 specific features were requested.
     */
    public static void send(Connection connection, Packet packet, List<String> to, List<String> cc, List<String> bcc,
            String replyTo, String replyRoom, boolean noReply) throws XMPPException {
        String serviceAddress = getMultipleRecipienServiceAddress(connection);
        if (serviceAddress != null) {
            // Send packet to target users using multiple recipient service provided by the server
            sendThroughService(connection, packet, to, cc, bcc, replyTo, replyRoom, noReply,
                    serviceAddress);
        }
        else {
            // Server does not support JEP-33 so try to send the packet to each recipient
            if (noReply || (replyTo != null && replyTo.trim().length() > 0) ||
                    (replyRoom != null && replyRoom.trim().length() > 0)) {
                // Some specified JEP-33 features were requested so throw an exception alerting
                // the user that this features are not available
                throw new XMPPException("Extended Stanza Addressing not supported by server");
            }
            // Send the packet to each individual recipient
            sendToIndividualRecipients(connection, packet, to, cc, bcc);
        }
    }

    /**
     * Sends a reply to a previously received packet that was sent to multiple recipients. Before
     * attempting to send the reply message some checkings are performed. If any of those checkings
     * fail then an XMPPException is going to be thrown with the specific error detail.
     *
     * @param connection the connection to use to send the reply.
     * @param original   the previously received packet that was sent to multiple recipients.
     * @param reply      the new message to send as a reply.
     * @throws XMPPException if the original message was not sent to multiple recipients, or the
     *                       original message cannot be replied or reply should be sent to a room.
     */
    public static void reply(Connection connection, Message original, Message reply)
            throws XMPPException {
        MultipleRecipientInfo info = getMultipleRecipientInfo(original);
        if (info == null) {
            throw new XMPPException("Original message does not contain multiple recipient info");
        }
        if (info.shouldNotReply()) {
            throw new XMPPException("Original message should not be replied");
        }
        if (info.getReplyRoom() != null) {
            throw new XMPPException("Reply should be sent through a room");
        }
        // Any <thread/> element from the initial message MUST be copied into the reply.
        if (original.getThread() != null) {
            reply.setThread(original.getThread());
        }
        MultipleAddresses.Address replyAddress = info.getReplyAddress();
        if (replyAddress != null && replyAddress.getJid() != null) {
            // Send reply to the reply_to address
            reply.setTo(replyAddress.getJid());
            connection.sendPacket(reply);
        }
        else {
            // Send reply to multiple recipients
            List<String> to = new ArrayList<String>();
            List<String> cc = new ArrayList<String>();
            for (Iterator<MultipleAddresses.Address> it = info.getTOAddresses().iterator(); it.hasNext();) {
                String jid = it.next().getJid();
                to.add(jid);
            }
            for (Iterator<MultipleAddresses.Address> it = info.getCCAddresses().iterator(); it.hasNext();) {
                String jid = it.next().getJid();
                cc.add(jid);
            }
            // Add original sender as a 'to' address (if not already present)
            if (!to.contains(original.getFrom()) && !cc.contains(original.getFrom())) {
                to.add(original.getFrom());
            }
            // Remove the sender from the TO/CC list (try with bare JID too)
            String from = connection.getUser();
            if (!to.remove(from) && !cc.remove(from)) {
                String bareJID = StringUtils.parseBareAddress(from);
                to.remove(bareJID);
                cc.remove(bareJID);
            }

            String serviceAddress = getMultipleRecipienServiceAddress(connection);
            if (serviceAddress != null) {
                // Send packet to target users using multiple recipient service provided by the server
                sendThroughService(connection, reply, to, cc, null, null, null, false,
                        serviceAddress);
            }
            else {
                // Server does not support JEP-33 so try to send the packet to each recipient
                sendToIndividualRecipients(connection, reply, to, cc, null);
            }
        }
    }

    /**
     * Returns the {@link MultipleRecipientInfo} contained in the specified packet or
     * <tt>null</tt> if none was found. Only packets sent to multiple recipients will
     * contain such information.
     *
     * @param packet the packet to check.
     * @return the MultipleRecipientInfo contained in the specified packet or <tt>null</tt>
     *         if none was found.
     */
    public static MultipleRecipientInfo getMultipleRecipientInfo(Packet packet) {
        MultipleAddresses extension = (MultipleAddresses) packet
                .getExtension("addresses", "http://jabber.org/protocol/address");
        return extension == null ? null : new MultipleRecipientInfo(extension);
    }

    private static void sendToIndividualRecipients(Connection connection, Packet packet,
            List<String> to, List<String> cc, List<String> bcc) {
        if (to != null) {
            for (Iterator<String> it = to.iterator(); it.hasNext();) {
                String jid = it.next();
                packet.setTo(jid);
                connection.sendPacket(new PacketCopy(packet.toXML()));
            }
        }
        if (cc != null) {
            for (Iterator<String> it = cc.iterator(); it.hasNext();) {
                String jid = it.next();
                packet.setTo(jid);
                connection.sendPacket(new PacketCopy(packet.toXML()));
            }
        }
        if (bcc != null) {
            for (Iterator<String> it = bcc.iterator(); it.hasNext();) {
                String jid = it.next();
                packet.setTo(jid);
                connection.sendPacket(new PacketCopy(packet.toXML()));
            }
        }
    }

    private static void sendThroughService(Connection connection, Packet packet, List<String> to,
            List<String> cc, List<String> bcc, String replyTo, String replyRoom, boolean noReply,
            String serviceAddress) {
        // Create multiple recipient extension
        MultipleAddresses multipleAddresses = new MultipleAddresses();
        if (to != null) {
            for (Iterator<String> it = to.iterator(); it.hasNext();) {
                String jid = it.next();
                multipleAddresses.addAddress(MultipleAddresses.TO, jid, null, null, false, null);
            }
        }
        if (cc != null) {
            for (Iterator<String> it = cc.iterator(); it.hasNext();) {
                String jid = it.next();
                multipleAddresses.addAddress(MultipleAddresses.CC, jid, null, null, false, null);
            }
        }
        if (bcc != null) {
            for (Iterator<String> it = bcc.iterator(); it.hasNext();) {
                String jid = it.next();
                multipleAddresses.addAddress(MultipleAddresses.BCC, jid, null, null, false, null);
            }
        }
        if (noReply) {
            multipleAddresses.setNoReply();
        }
        else {
            if (replyTo != null && replyTo.trim().length() > 0) {
                multipleAddresses
                        .addAddress(MultipleAddresses.REPLY_TO, replyTo, null, null, false, null);
            }
            if (replyRoom != null && replyRoom.trim().length() > 0) {
                multipleAddresses.addAddress(MultipleAddresses.REPLY_ROOM, replyRoom, null, null,
                        false, null);
            }
        }
        // Set the multiple recipient service address as the target address
        packet.setTo(serviceAddress);
        // Add extension to packet
        packet.addExtension(multipleAddresses);
        // Send the packet
        connection.sendPacket(packet);
    }

    /**
     * Returns the address of the multiple recipients service. To obtain such address service
     * discovery is going to be used on the connected server and if none was found then another
     * attempt will be tried on the server items. The discovered information is going to be
     * cached for 24 hours.
     *
     * @param connection the connection to use for disco. The connected server is going to be
     *                   queried.
     * @return the address of the multiple recipients service or <tt>null</tt> if none was found.
     */
    private static String getMultipleRecipienServiceAddress(Connection connection) {
        String serviceName = connection.getServiceName();
        String serviceAddress = (String) services.get(serviceName);
        if (serviceAddress == null) {
            synchronized (services) {
                serviceAddress = (String) services.get(serviceName);
                if (serviceAddress == null) {

                    // Send the disco packet to the server itself
                    try {
                        DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection)
                                .discoverInfo(serviceName);
                        // Check if the server supports JEP-33
                        if (info.containsFeature("http://jabber.org/protocol/address")) {
                            serviceAddress = serviceName;
                        }
                        else {
                            // Get the disco items and send the disco packet to each server item
                            DiscoverItems items = ServiceDiscoveryManager.getInstanceFor(connection)
                                    .discoverItems(serviceName);
                            for (Iterator<DiscoverItems.Item> it = items.getItems(); it.hasNext();) {
                                DiscoverItems.Item item = it.next();
                                info = ServiceDiscoveryManager.getInstanceFor(connection)
                                        .discoverInfo(item.getEntityID(), item.getNode());
                                if (info.containsFeature("http://jabber.org/protocol/address")) {
                                    serviceAddress = serviceName;
                                    break;
                                }
                            }

                        }
                        // Cache the discovered information
                        services.put(serviceName, serviceAddress == null ? "" : serviceAddress);
                    }
                    catch (XMPPException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return "".equals(serviceAddress) ? null : serviceAddress;
    }

    /**
     * Packet that holds the XML stanza to send. This class is useful when the same packet
     * is needed to be sent to different recipients. Since using the same packet is not possible
     * (i.e. cannot change the TO address of a queues packet to be sent) then this class was
     * created to keep the XML stanza to send.
     */
    private static class PacketCopy extends Packet {

        private String text;

        /**
         * Create a copy of a packet with the text to send. The passed text must be a valid text to
         * send to the server, no validation will be done on the passed text.
         *
         * @param text the whole text of the packet to send
         */
        public PacketCopy(String text) {
            this.text = text;
        }

        public String toXML() {
            return text;
        }

    }

}
