/**
 * $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 java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.filter.PacketExtensionFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.packet.MessageEvent;

/**
 * Manages message events requests and notifications. A MessageEventManager provides a high
 * level access to request for notifications and send event notifications. It also provides 
 * an easy way to hook up custom logic when requests or notifications are received. 
 *
 * @author Gaston Dombiak
 */
public class MessageEventManager {

    private List<MessageEventNotificationListener> messageEventNotificationListeners = new ArrayList<MessageEventNotificationListener>();
    private List<MessageEventRequestListener> messageEventRequestListeners = new ArrayList<MessageEventRequestListener>();

    private Connection con;

    private PacketFilter packetFilter = new PacketExtensionFilter("x", "jabber:x:event");
    private PacketListener packetListener;

    /**
     * Creates a new message event manager.
     *
     * @param con a Connection to a XMPP server.
     */
    public MessageEventManager(Connection con) {
        this.con = con;
        init();
    }

    /**
     * Adds event notification requests to a message. For each event type that
     * the user wishes event notifications from the message recepient for, <tt>true</tt>
     * should be passed in to this method.
     * 
     * @param message the message to add the requested notifications.
     * @param offline specifies if the offline event is requested.
     * @param delivered specifies if the delivered event is requested.
     * @param displayed specifies if the displayed event is requested.
     * @param composing specifies if the composing event is requested.
     */
    public static void addNotificationsRequests(Message message, boolean offline,
            boolean delivered, boolean displayed, boolean composing)
    {
        // Create a MessageEvent Package and add it to the message
        MessageEvent messageEvent = new MessageEvent();
        messageEvent.setOffline(offline);
        messageEvent.setDelivered(delivered);
        messageEvent.setDisplayed(displayed);
        messageEvent.setComposing(composing);
        message.addExtension(messageEvent);
    }

    /**
     * Adds a message event request listener. The listener will be fired anytime a request for
     * event notification is received.
     *
     * @param messageEventRequestListener a message event request listener.
     */
    public void addMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) {
        synchronized (messageEventRequestListeners) {
            if (!messageEventRequestListeners.contains(messageEventRequestListener)) {
                messageEventRequestListeners.add(messageEventRequestListener);
            }
        }
    }

    /**
     * Removes a message event request listener. The listener will be fired anytime a request for
     * event notification is received.
     *
     * @param messageEventRequestListener a message event request listener.
     */
    public void removeMessageEventRequestListener(MessageEventRequestListener messageEventRequestListener) {
        synchronized (messageEventRequestListeners) {
            messageEventRequestListeners.remove(messageEventRequestListener);
        }
    }

    /**
     * Adds a message event notification listener. The listener will be fired anytime a notification
     * event is received.
     *
     * @param messageEventNotificationListener a message event notification listener.
     */
    public void addMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
        synchronized (messageEventNotificationListeners) {
            if (!messageEventNotificationListeners.contains(messageEventNotificationListener)) {
                messageEventNotificationListeners.add(messageEventNotificationListener);
            }
        }
    }

    /**
     * Removes a message event notification listener. The listener will be fired anytime a notification
     * event is received.
     *
     * @param messageEventNotificationListener a message event notification listener.
     */
    public void removeMessageEventNotificationListener(MessageEventNotificationListener messageEventNotificationListener) {
        synchronized (messageEventNotificationListeners) {
            messageEventNotificationListeners.remove(messageEventNotificationListener);
        }
    }

    /**
     * Fires message event request listeners.
     */
    private void fireMessageEventRequestListeners(
        String from,
        String packetID,
        String methodName) {
        MessageEventRequestListener[] listeners = null;
        Method method;
        synchronized (messageEventRequestListeners) {
            listeners = new MessageEventRequestListener[messageEventRequestListeners.size()];
            messageEventRequestListeners.toArray(listeners);
        }
        try {
            method =
                MessageEventRequestListener.class.getDeclaredMethod(
                    methodName,
                    new Class[] { String.class, String.class, MessageEventManager.class });
            for (int i = 0; i < listeners.length; i++) {
                method.invoke(listeners[i], new Object[] { from, packetID, this });
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * Fires message event notification listeners.
     */
    private void fireMessageEventNotificationListeners(
        String from,
        String packetID,
        String methodName) {
        MessageEventNotificationListener[] listeners = null;
        Method method;
        synchronized (messageEventNotificationListeners) {
            listeners =
                new MessageEventNotificationListener[messageEventNotificationListeners.size()];
            messageEventNotificationListeners.toArray(listeners);
        }
        try {
            method =
                MessageEventNotificationListener.class.getDeclaredMethod(
                    methodName,
                    new Class[] { String.class, String.class });
            for (int i = 0; i < listeners.length; i++) {
                method.invoke(listeners[i], new Object[] { from, packetID });
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void init() {
        // Listens for all message event packets and fire the proper message event listeners.
        packetListener = new PacketListener() {
            public void processPacket(Packet packet) {
                Message message = (Message) packet;
                MessageEvent messageEvent =
                    (MessageEvent) message.getExtension("x", "jabber:x:event");
                if (messageEvent.isMessageEventRequest()) {
                    // Fire event for requests of message events
                    for (Iterator<String> it = messageEvent.getEventTypes(); it.hasNext();)
                        fireMessageEventRequestListeners(
                            message.getFrom(),
                            message.getPacketID(),
                            it.next().concat("NotificationRequested"));
                } else
                    // Fire event for notifications of message events
                    for (Iterator<String> it = messageEvent.getEventTypes(); it.hasNext();)
                        fireMessageEventNotificationListeners(
                            message.getFrom(),
                            messageEvent.getPacketID(),
                            it.next().concat("Notification"));

            };

        };
        con.addPacketListener(packetListener, packetFilter);
    }

    /**
     * Sends the notification that the message was delivered to the sender of the original message
     * 
     * @param to the recipient of the notification.
     * @param packetID the id of the message to send.
     */
    public void sendDeliveredNotification(String to, String packetID) {
        // Create the message to send
        Message msg = new Message(to);
        // Create a MessageEvent Package and add it to the message
        MessageEvent messageEvent = new MessageEvent();
        messageEvent.setDelivered(true);
        messageEvent.setPacketID(packetID);
        msg.addExtension(messageEvent);
        // Send the packet
        con.sendPacket(msg);
    }

    /**
     * Sends the notification that the message was displayed to the sender of the original message
     * 
     * @param to the recipient of the notification.
     * @param packetID the id of the message to send.
     */
    public void sendDisplayedNotification(String to, String packetID) {
        // Create the message to send
        Message msg = new Message(to);
        // Create a MessageEvent Package and add it to the message
        MessageEvent messageEvent = new MessageEvent();
        messageEvent.setDisplayed(true);
        messageEvent.setPacketID(packetID);
        msg.addExtension(messageEvent);
        // Send the packet
        con.sendPacket(msg);
    }

    /**
     * Sends the notification that the receiver of the message is composing a reply
     * 
     * @param to the recipient of the notification.
     * @param packetID the id of the message to send.
     */
    public void sendComposingNotification(String to, String packetID) {
        // Create the message to send
        Message msg = new Message(to);
        // Create a MessageEvent Package and add it to the message
        MessageEvent messageEvent = new MessageEvent();
        messageEvent.setComposing(true);
        messageEvent.setPacketID(packetID);
        msg.addExtension(messageEvent);
        // Send the packet
        con.sendPacket(msg);
    }

    /**
     * Sends the notification that the receiver of the message has cancelled composing a reply.
     * 
     * @param to the recipient of the notification.
     * @param packetID the id of the message to send.
     */
    public void sendCancelledNotification(String to, String packetID) {
        // Create the message to send
        Message msg = new Message(to);
        // Create a MessageEvent Package and add it to the message
        MessageEvent messageEvent = new MessageEvent();
        messageEvent.setCancelled(true);
        messageEvent.setPacketID(packetID);
        msg.addExtension(messageEvent);
        // Send the packet
        con.sendPacket(msg);
    }

    public void destroy() {
        if (con != null) {
            con.removePacketListener(packetListener);
        }
    }

    protected void finalize() throws Throwable {
        destroy();
        super.finalize();
    }
}