/**
 * $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.smack;

import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.RosterPacket;
import org.jivesoftware.smack.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Represents a user's roster, which is the collection of users a person receives
 * presence updates for. Roster items are categorized into groups for easier management.<p>
 * <p/>
 * Others users may attempt to subscribe to this user using a subscription request. Three
 * modes are supported for handling these requests: <ul>
 * <li>{@link SubscriptionMode#accept_all accept_all} -- accept all subscription requests.</li>
 * <li>{@link SubscriptionMode#reject_all reject_all} -- reject all subscription requests.</li>
 * <li>{@link SubscriptionMode#manual manual} -- manually process all subscription requests.</li>
 * </ul>
 *
 * @author Matt Tucker
 * @see Connection#getRoster()
 */
public class Roster {

    /**
     * The default subscription processing mode to use when a Roster is created. By default
     * all subscription requests are automatically accepted.
     */
    private static SubscriptionMode defaultSubscriptionMode = SubscriptionMode.accept_all;
    private RosterStorage persistentStorage;

    private Connection connection;
    private final Map<String, RosterGroup> groups;
    private final Map<String,RosterEntry> entries;
    private final List<RosterEntry> unfiledEntries;
    private final List<RosterListener> rosterListeners;
    private Map<String, Map<String, Presence>> presenceMap;
    // The roster is marked as initialized when at least a single roster packet
    // has been received and processed.
    boolean rosterInitialized = false;
    private PresencePacketListener presencePacketListener;

    private SubscriptionMode subscriptionMode = getDefaultSubscriptionMode();
    
    private String requestPacketId;

    /**
     * Returns the default subscription processing mode to use when a new Roster is created. The
     * subscription processing mode dictates what action Smack will take when subscription
     * requests from other users are made. The default subscription mode
     * is {@link SubscriptionMode#accept_all}.
     *
     * @return the default subscription mode to use for new Rosters
     */
    public static SubscriptionMode getDefaultSubscriptionMode() {
        return defaultSubscriptionMode;
    }

    /**
     * Sets the default subscription processing mode to use when a new Roster is created. The
     * subscription processing mode dictates what action Smack will take when subscription
     * requests from other users are made. The default subscription mode
     * is {@link SubscriptionMode#accept_all}.
     *
     * @param subscriptionMode the default subscription mode to use for new Rosters.
     */
    public static void setDefaultSubscriptionMode(SubscriptionMode subscriptionMode) {
        defaultSubscriptionMode = subscriptionMode;
    }
    
    Roster(final Connection connection, RosterStorage persistentStorage){
    	this(connection);
    	this.persistentStorage = persistentStorage;
    }

    /**
     * Creates a new roster.
     *
     * @param connection an XMPP connection.
     */
    Roster(final Connection connection) {
        this.connection = connection;
        //Disable roster versioning if server doesn't offer support for it
        if(!connection.getConfiguration().isRosterVersioningAvailable()){
        	persistentStorage=null;
        }
        groups = new ConcurrentHashMap<String, RosterGroup>();
        unfiledEntries = new CopyOnWriteArrayList<RosterEntry>();
        entries = new ConcurrentHashMap<String,RosterEntry>();
        rosterListeners = new CopyOnWriteArrayList<RosterListener>();
        presenceMap = new ConcurrentHashMap<String, Map<String, Presence>>();
        // Listen for any roster packets.
        PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class);
        connection.addPacketListener(new RosterPacketListener(), rosterFilter);
        // Listen for any presence packets.
        PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);
        presencePacketListener = new PresencePacketListener();
        connection.addPacketListener(presencePacketListener, presenceFilter);
        
        // Listen for connection events
        final ConnectionListener connectionListener = new AbstractConnectionListener() {
            
            public void connectionClosed() {
                // Changes the presence available contacts to unavailable
                setOfflinePresences();
            }

            public void connectionClosedOnError(Exception e) {
                // Changes the presence available contacts to unavailable
                setOfflinePresences();
            }

        };
        
        // if not connected add listener after successful login
        if(!this.connection.isConnected()) {
            Connection.addConnectionCreationListener(new ConnectionCreationListener() {
                
                public void connectionCreated(Connection connection) {
                    if(connection.equals(Roster.this.connection)) {
                        Roster.this.connection.addConnectionListener(connectionListener);
                    }
                    
                }
            });
        } else {
            connection.addConnectionListener(connectionListener);
        }
    }

    /**
     * Returns the subscription processing mode, which dictates what action
     * Smack will take when subscription requests from other users are made.
     * The default subscription mode is {@link SubscriptionMode#accept_all}.<p>
     * <p/>
     * If using the manual mode, a PacketListener should be registered that
     * listens for Presence packets that have a type of
     * {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}.
     *
     * @return the subscription mode.
     */
    public SubscriptionMode getSubscriptionMode() {
        return subscriptionMode;
    }

    /**
     * Sets the subscription processing mode, which dictates what action
     * Smack will take when subscription requests from other users are made.
     * The default subscription mode is {@link SubscriptionMode#accept_all}.<p>
     * <p/>
     * If using the manual mode, a PacketListener should be registered that
     * listens for Presence packets that have a type of
     * {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}.
     *
     * @param subscriptionMode the subscription mode.
     */
    public void setSubscriptionMode(SubscriptionMode subscriptionMode) {
        this.subscriptionMode = subscriptionMode;
    }

    /**
     * Reloads the entire roster from the server. This is an asynchronous operation,
     * which means the method will return immediately, and the roster will be
     * reloaded at a later point when the server responds to the reload request.
     * 
     * @throws IllegalStateException if connection is not logged in or logged in anonymously
     */
    public void reload() {
        if (!connection.isAuthenticated()) {
            throw new IllegalStateException("Not logged in to server.");
        }
        if (connection.isAnonymous()) {
            throw new IllegalStateException("Anonymous users can't have a roster.");
        }

    	RosterPacket packet = new RosterPacket();
    	if(persistentStorage!=null){
    		packet.setVersion(persistentStorage.getRosterVersion());
    	}
    	requestPacketId = packet.getPacketID();
    	PacketFilter idFilter = new PacketIDFilter(requestPacketId);
    	connection.addPacketListener(new RosterResultListener(), idFilter);
        connection.sendPacket(packet);
    }

    /**
     * Adds a listener to this roster. The listener will be fired anytime one or more
     * changes to the roster are pushed from the server.
     *
     * @param rosterListener a roster listener.
     */
    public void addRosterListener(RosterListener rosterListener) {
        if (!rosterListeners.contains(rosterListener)) {
            rosterListeners.add(rosterListener);
        }
    }

    /**
     * Removes a listener from this roster. The listener will be fired anytime one or more
     * changes to the roster are pushed from the server.
     *
     * @param rosterListener a roster listener.
     */
    public void removeRosterListener(RosterListener rosterListener) {
        rosterListeners.remove(rosterListener);
    }

    /**
     * Creates a new group.<p>
     * <p/>
     * Note: you must add at least one entry to the group for the group to be kept
     * after a logout/login. This is due to the way that XMPP stores group information.
     *
     * @param name the name of the group.
     * @return a new group.
     * @throws IllegalStateException if connection is not logged in or logged in anonymously
     */
    public RosterGroup createGroup(String name) {
        if (!connection.isAuthenticated()) {
            throw new IllegalStateException("Not logged in to server.");
        }
        if (connection.isAnonymous()) {
            throw new IllegalStateException("Anonymous users can't have a roster.");
        }
        if (groups.containsKey(name)) {
            throw new IllegalArgumentException("Group with name " + name + " alread exists.");
        }
        
        RosterGroup group = new RosterGroup(name, connection);
        groups.put(name, group);
        return group;
    }

    /**
     * Creates a new roster entry and presence subscription. The server will asynchronously
     * update the roster with the subscription status.
     *
     * @param user   the user. (e.g. johndoe@jabber.org)
     * @param name   the nickname of the user.
     * @param groups the list of group names the entry will belong to, or <tt>null</tt> if the
     *               the roster entry won't belong to a group.
     * @throws XMPPException if an XMPP exception occurs.
     * @throws IllegalStateException if connection is not logged in or logged in anonymously
     */
    public void createEntry(String user, String name, String[] groups) throws XMPPException {
        if (!connection.isAuthenticated()) {
            throw new IllegalStateException("Not logged in to server.");
        }
        if (connection.isAnonymous()) {
            throw new IllegalStateException("Anonymous users can't have a roster.");
        }

        // Create and send roster entry creation packet.
        RosterPacket rosterPacket = new RosterPacket();
        rosterPacket.setType(IQ.Type.SET);
        RosterPacket.Item item = new RosterPacket.Item(user, name);
        if (groups != null) {
            for (String group : groups) {
                if (group != null && group.trim().length() > 0) {
                    item.addGroupName(group);
                }
            }
        }
        rosterPacket.addRosterItem(item);
        // Wait up to a certain number of seconds for a reply from the server.
        PacketCollector collector = connection.createPacketCollector(
                new PacketIDFilter(rosterPacket.getPacketID()));
        connection.sendPacket(rosterPacket);
        IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
        collector.cancel();
        if (response == null) {
            throw new XMPPException("No response from the server.");
        }
        // If the server replied with an error, throw an exception.
        else if (response.getType() == IQ.Type.ERROR) {
            throw new XMPPException(response.getError());
        }

        // Create a presence subscription packet and send.
        Presence presencePacket = new Presence(Presence.Type.subscribe);
        presencePacket.setTo(user);
        connection.sendPacket(presencePacket);
    }
    
    private void insertRosterItems(List<RosterPacket.Item> items){
    	 Collection<String> addedEntries = new ArrayList<String>();
         Collection<String> updatedEntries = new ArrayList<String>();
         Collection<String> deletedEntries = new ArrayList<String>();
         Iterator<RosterPacket.Item> iter = items.iterator();
         while(iter.hasNext()){
        	 insertRosterItem(iter.next(), addedEntries,updatedEntries,deletedEntries);
         }
         fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
    }
    
    private void insertRosterItem(RosterPacket.Item item, Collection<String> addedEntries,
    		Collection<String> updatedEntries, Collection<String> deletedEntries){
    	RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
                item.getItemType(), item.getItemStatus(), this, connection);

        // If the packet is of the type REMOVE then remove the entry
        if (RosterPacket.ItemType.remove.equals(item.getItemType())) {
            // Remove the entry from the entry list.
            if (entries.containsKey(item.getUser())) {
                entries.remove(item.getUser());
            }
            // Remove the entry from the unfiled entry list.
            if (unfiledEntries.contains(entry)) {
                unfiledEntries.remove(entry);
            }
            // Removing the user from the roster, so remove any presence information
            // about them.
            String key = StringUtils.parseName(item.getUser()) + "@" +
                    StringUtils.parseServer(item.getUser());
            presenceMap.remove(key);
            // Keep note that an entry has been removed
            if(deletedEntries!=null){
            	deletedEntries.add(item.getUser());
            }
        }
        else {
            // Make sure the entry is in the entry list.
            if (!entries.containsKey(item.getUser())) {
                entries.put(item.getUser(), entry);
                // Keep note that an entry has been added
                if(addedEntries!=null){
                	addedEntries.add(item.getUser());
                }
            }
            else {
                // If the entry was in then list then update its state with the new values
                entries.put(item.getUser(), entry);
                
                // Keep note that an entry has been updated
                if(updatedEntries!=null){
                	updatedEntries.add(item.getUser());
                }
            }
            // If the roster entry belongs to any groups, remove it from the
            // list of unfiled entries.
            if (!item.getGroupNames().isEmpty()) {
                unfiledEntries.remove(entry);
            }
            // Otherwise add it to the list of unfiled entries.
            else {
                if (!unfiledEntries.contains(entry)) {
                    unfiledEntries.add(entry);
                }
            }
        }

        // Find the list of groups that the user currently belongs to.
        List<String> currentGroupNames = new ArrayList<String>();
        for (RosterGroup group: getGroups()) {
            if (group.contains(entry)) {
                currentGroupNames.add(group.getName());
            }
        }

        // If the packet is not of the type REMOVE then add the entry to the groups
        if (!RosterPacket.ItemType.remove.equals(item.getItemType())) {
            // Create the new list of groups the user belongs to.
            List<String> newGroupNames = new ArrayList<String>();
            for (String groupName : item.getGroupNames()) {
                // Add the group name to the list.
                newGroupNames.add(groupName);

                // Add the entry to the group.
                RosterGroup group = getGroup(groupName);
                if (group == null) {
                    group = createGroup(groupName);
                    groups.put(groupName, group);
                }
                // Add the entry.
                group.addEntryLocal(entry);
            }

            // We have the list of old and new group names. We now need to
            // remove the entry from the all the groups it may no longer belong
            // to. We do this by subracting the new group set from the old.
            for (String newGroupName : newGroupNames) {
                currentGroupNames.remove(newGroupName);
            }
        }

        // Loop through any groups that remain and remove the entries.
        // This is neccessary for the case of remote entry removals.
        for (String groupName : currentGroupNames) {
            RosterGroup group = getGroup(groupName);
            group.removeEntryLocal(entry);
            if (group.getEntryCount() == 0) {
                groups.remove(groupName);
            }
        }
        // Remove all the groups with no entries. We have to do this because
        // RosterGroup.removeEntry removes the entry immediately (locally) and the
        // group could remain empty.
        // TODO Check the performance/logic for rosters with large number of groups
        for (RosterGroup group : getGroups()) {
            if (group.getEntryCount() == 0) {
                groups.remove(group.getName());
            }
        }
    }

    /**
     * Removes a roster entry from the roster. The roster entry will also be removed from the
     * unfiled entries or from any roster group where it could belong and will no longer be part
     * of the roster. Note that this is an asynchronous call -- Smack must wait for the server
     * to send an updated subscription status.
     *
     * @param entry a roster entry.
     * @throws XMPPException if an XMPP error occurs.
     * @throws IllegalStateException if connection is not logged in or logged in anonymously
     */
    public void removeEntry(RosterEntry entry) throws XMPPException {
        if (!connection.isAuthenticated()) {
            throw new IllegalStateException("Not logged in to server.");
        }
        if (connection.isAnonymous()) {
            throw new IllegalStateException("Anonymous users can't have a roster.");
        }

        // Only remove the entry if it's in the entry list.
        // The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet)
        if (!entries.containsKey(entry.getUser())) {
            return;
        }
        RosterPacket packet = new RosterPacket();
        packet.setType(IQ.Type.SET);
        RosterPacket.Item item = RosterEntry.toRosterItem(entry);
        // Set the item type as REMOVE so that the server will delete the entry
        item.setItemType(RosterPacket.ItemType.remove);
        packet.addRosterItem(item);
        PacketCollector collector = connection.createPacketCollector(
                new PacketIDFilter(packet.getPacketID()));
        connection.sendPacket(packet);
        IQ response = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
        collector.cancel();
        if (response == null) {
            throw new XMPPException("No response from the server.");
        }
        // If the server replied with an error, throw an exception.
        else if (response.getType() == IQ.Type.ERROR) {
            throw new XMPPException(response.getError());
        }
    }

    /**
     * Returns a count of the entries in the roster.
     *
     * @return the number of entries in the roster.
     */
    public int getEntryCount() {
        return getEntries().size();
    }

    /**
     * Returns an unmodifiable collection of all entries in the roster, including entries
     * that don't belong to any groups.
     *
     * @return all entries in the roster.
     */
    public Collection<RosterEntry> getEntries() {
        Set<RosterEntry> allEntries = new HashSet<RosterEntry>();
        // Loop through all roster groups and add their entries to the answer
        for (RosterGroup rosterGroup : getGroups()) {
            allEntries.addAll(rosterGroup.getEntries());
        }
        // Add the roster unfiled entries to the answer
        allEntries.addAll(unfiledEntries);

        return Collections.unmodifiableCollection(allEntries);
    }

    /**
     * Returns a count of the unfiled entries in the roster. An unfiled entry is
     * an entry that doesn't belong to any groups.
     *
     * @return the number of unfiled entries in the roster.
     */
    public int getUnfiledEntryCount() {
        return unfiledEntries.size();
    }

    /**
     * Returns an unmodifiable collection for the unfiled roster entries. An unfiled entry is
     * an entry that doesn't belong to any groups.
     *
     * @return the unfiled roster entries.
     */
    public Collection<RosterEntry> getUnfiledEntries() {
        return Collections.unmodifiableList(unfiledEntries);
    }

    /**
     * Returns the roster entry associated with the given XMPP address or
     * <tt>null</tt> if the user is not an entry in the roster.
     *
     * @param user the XMPP address of the user (eg "jsmith@example.com"). The address could be
     *             in any valid format (e.g. "domain/resource", "user@domain" or "user@domain/resource").
     * @return the roster entry or <tt>null</tt> if it does not exist.
     */
    public RosterEntry getEntry(String user) {
        if (user == null) {
            return null;
        }
        return entries.get(user.toLowerCase());
    }

    /**
     * Returns true if the specified XMPP address is an entry in the roster.
     *
     * @param user the XMPP address of the user (eg "jsmith@example.com"). The
     *             address could be in any valid format (e.g. "domain/resource",
     *             "user@domain" or "user@domain/resource").
     * @return true if the XMPP address is an entry in the roster.
     */
    public boolean contains(String user) {
        return getEntry(user) != null;
    }

    /**
     * Returns the roster group with the specified name, or <tt>null</tt> if the
     * group doesn't exist.
     *
     * @param name the name of the group.
     * @return the roster group with the specified name.
     */
    public RosterGroup getGroup(String name) {
        return groups.get(name);
    }

    /**
     * Returns the number of the groups in the roster.
     *
     * @return the number of groups in the roster.
     */
    public int getGroupCount() {
        return groups.size();
    }

    /**
     * Returns an unmodifiable collections of all the roster groups.
     *
     * @return an iterator for all roster groups.
     */
    public Collection<RosterGroup> getGroups() {
        return Collections.unmodifiableCollection(groups.values());
    }

    /**
     * Returns the presence info for a particular user. If the user is offline, or
     * if no presence data is available (such as when you are not subscribed to the
     * user's presence updates), unavailable presence will be returned.<p>
     * <p/>
     * If the user has several presences (one for each resource), then the presence with
     * highest priority will be returned. If multiple presences have the same priority,
     * the one with the "most available" presence mode will be returned. In order,
     * that's {@link org.jivesoftware.smack.packet.Presence.Mode#chat free to chat},
     * {@link org.jivesoftware.smack.packet.Presence.Mode#available available},
     * {@link org.jivesoftware.smack.packet.Presence.Mode#away away},
     * {@link org.jivesoftware.smack.packet.Presence.Mode#xa extended away}, and
     * {@link org.jivesoftware.smack.packet.Presence.Mode#dnd do not disturb}.<p>
     * <p/>
     * Note that presence information is received asynchronously. So, just after logging
     * in to the server, presence values for users in the roster may be unavailable
     * even if they are actually online. In other words, the value returned by this
     * method should only be treated as a snapshot in time, and may not accurately reflect
     * other user's presence instant by instant. If you need to track presence over time,
     * such as when showing a visual representation of the roster, consider using a
     * {@link RosterListener}.
     *
     * @param user an XMPP ID. The address could be in any valid format (e.g.
     *             "domain/resource", "user@domain" or "user@domain/resource"). Any resource
     *             information that's part of the ID will be discarded.
     * @return the user's current presence, or unavailable presence if the user is offline
     *         or if no presence information is available..
     */
    public Presence getPresence(String user) {
        String key = getPresenceMapKey(StringUtils.parseBareAddress(user));
        Map<String, Presence> userPresences = presenceMap.get(key);
        if (userPresences == null) {
            Presence presence = new Presence(Presence.Type.unavailable);
            presence.setFrom(user);
            return presence;
        }
        else {
            // Find the resource with the highest priority
            // Might be changed to use the resource with the highest availability instead.
            Presence presence = null;

            for (String resource : userPresences.keySet()) {
                Presence p = userPresences.get(resource);
                if (!p.isAvailable()) {
                    continue;
                }
                // Chose presence with highest priority first.
                if (presence == null || p.getPriority() > presence.getPriority()) {
                    presence = p;
                }
                // If equal priority, choose "most available" by the mode value.
                else if (p.getPriority() == presence.getPriority()) {
                    Presence.Mode pMode = p.getMode();
                    // Default to presence mode of available.
                    if (pMode == null) {
                        pMode = Presence.Mode.available;
                    }
                    Presence.Mode presenceMode = presence.getMode();
                    // Default to presence mode of available.
                    if (presenceMode == null) {
                        presenceMode = Presence.Mode.available;
                    }
                    if (pMode.compareTo(presenceMode) < 0) {
                        presence = p;
                    }
                }
            }
            if (presence == null) {
                presence = new Presence(Presence.Type.unavailable);
                presence.setFrom(user);
                return presence;
            }
            else {
                return presence;
            }
        }
    }

    /**
     * Returns the presence info for a particular user's resource, or unavailable presence
     * if the user is offline or if no presence information is available, such as
     * when you are not subscribed to the user's presence updates.
     *
     * @param userWithResource a fully qualified XMPP ID including a resource (user@domain/resource).
     * @return the user's current presence, or unavailable presence if the user is offline
     *         or if no presence information is available.
     */
    public Presence getPresenceResource(String userWithResource) {
        String key = getPresenceMapKey(userWithResource);
        String resource = StringUtils.parseResource(userWithResource);
        Map<String, Presence> userPresences = presenceMap.get(key);
        if (userPresences == null) {
            Presence presence = new Presence(Presence.Type.unavailable);
            presence.setFrom(userWithResource);
            return presence;
        }
        else {
            Presence presence = userPresences.get(resource);
            if (presence == null) {
                presence = new Presence(Presence.Type.unavailable);
                presence.setFrom(userWithResource);
                return presence;
            }
            else {
                return presence;
            }
        }
    }

    /**
     * Returns an iterator (of Presence objects) for all of a user's current presences
     * or an unavailable presence if the user is unavailable (offline) or if no presence
     * information is available, such as when you are not subscribed to the user's presence
     * updates.
     *
     * @param user a XMPP ID, e.g. jdoe@example.com.
     * @return an iterator (of Presence objects) for all the user's current presences,
     *         or an unavailable presence if the user is offline or if no presence information
     *         is available.
     */
    public Iterator<Presence> getPresences(String user) {
        String key = getPresenceMapKey(user);
        Map<String, Presence> userPresences = presenceMap.get(key);
        if (userPresences == null) {
            Presence presence = new Presence(Presence.Type.unavailable);
            presence.setFrom(user);
            return Arrays.asList(presence).iterator();
        }
        else {
            Collection<Presence> answer = new ArrayList<Presence>();
            for (Presence presence : userPresences.values()) {
                if (presence.isAvailable()) {
                    answer.add(presence);
                }
            }
            if (!answer.isEmpty()) {
                return answer.iterator();
            }
            else {
                Presence presence = new Presence(Presence.Type.unavailable);
                presence.setFrom(user);
                return Arrays.asList(presence).iterator();    
            }
        }
    }

    /**
     * Cleans up all resources used by the roster.
     */
    void cleanup() {
        rosterListeners.clear();
    }

    /**
     * Returns the key to use in the presenceMap for a fully qualified XMPP ID.
     * The roster can contain any valid address format such us "domain/resource",
     * "user@domain" or "user@domain/resource". If the roster contains an entry
     * associated with the fully qualified XMPP ID then use the fully qualified XMPP
     * ID as the key in presenceMap, otherwise use the bare address. Note: When the
     * key in presenceMap is a fully qualified XMPP ID, the userPresences is useless
     * since it will always contain one entry for the user.
     *
     * @param user the bare or fully qualified XMPP ID, e.g. jdoe@example.com or
     *             jdoe@example.com/Work.
     * @return the key to use in the presenceMap for the fully qualified XMPP ID.
     */
    private String getPresenceMapKey(String user) {
        if (user == null) {
            return null;
        }
        String key = user;
        if (!contains(user)) {
            key = StringUtils.parseBareAddress(user);
        }
        return key.toLowerCase();
    }

    /**
     * Changes the presence of available contacts offline by simulating an unavailable
     * presence sent from the server. After a disconnection, every Presence is set
     * to offline.
     */
    private void setOfflinePresences() {
        Presence packetUnavailable;
        for (String user : presenceMap.keySet()) {
            Map<String, Presence> resources = presenceMap.get(user);
            if (resources != null) {
                for (String resource : resources.keySet()) {
                    packetUnavailable = new Presence(Presence.Type.unavailable);
                    packetUnavailable.setFrom(user + "/" + resource);
                    presencePacketListener.processPacket(packetUnavailable);
                }
            }
        }
    }

    /**
     * Fires roster changed event to roster listeners indicating that the
     * specified collections of contacts have been added, updated or deleted
     * from the roster.
     *
     * @param addedEntries   the collection of address of the added contacts.
     * @param updatedEntries the collection of address of the updated contacts.
     * @param deletedEntries the collection of address of the deleted contacts.
     */
    private void fireRosterChangedEvent(Collection<String> addedEntries, Collection<String> updatedEntries,
            Collection<String> deletedEntries) {
        for (RosterListener listener : rosterListeners) {
            if (!addedEntries.isEmpty()) {
                listener.entriesAdded(addedEntries);
            }
            if (!updatedEntries.isEmpty()) {
                listener.entriesUpdated(updatedEntries);
            }
            if (!deletedEntries.isEmpty()) {
                listener.entriesDeleted(deletedEntries);
            }
        }
    }

    /**
     * Fires roster presence changed event to roster listeners.
     *
     * @param presence the presence change.
     */
    private void fireRosterPresenceEvent(Presence presence) {
        for (RosterListener listener : rosterListeners) {
            listener.presenceChanged(presence);
        }
    }

    /**
     * An enumeration for the subscription mode options.
     */
    public enum SubscriptionMode {

        /**
         * Automatically accept all subscription and unsubscription requests. This is
         * the default mode and is suitable for simple client. More complex client will
         * likely wish to handle subscription requests manually.
         */
        accept_all,

        /**
         * Automatically reject all subscription requests.
         */
        reject_all,

        /**
         * Subscription requests are ignored, which means they must be manually
         * processed by registering a listener for presence packets and then looking
         * for any presence requests that have the type Presence.Type.SUBSCRIBE or
         * Presence.Type.UNSUBSCRIBE.
         */
        manual
    }

    /**
     * Listens for all presence packets and processes them.
     */
    private class PresencePacketListener implements PacketListener {

        public void processPacket(Packet packet) {
            Presence presence = (Presence) packet;
            String from = presence.getFrom();
            String key = getPresenceMapKey(from);

            // If an "available" presence, add it to the presence map. Each presence
            // map will hold for a particular user a map with the presence
            // packets saved for each resource.
            if (presence.getType() == Presence.Type.available) {
                Map<String, Presence> userPresences;
                // Get the user presence map
                if (presenceMap.get(key) == null) {
                    userPresences = new ConcurrentHashMap<String, Presence>();
                    presenceMap.put(key, userPresences);
                }
                else {
                    userPresences = presenceMap.get(key);
                }
                // See if an offline presence was being stored in the map. If so, remove
                // it since we now have an online presence.
                userPresences.remove("");
                // Add the new presence, using the resources as a key.
                userPresences.put(StringUtils.parseResource(from), presence);
                // If the user is in the roster, fire an event.
                RosterEntry entry = entries.get(key);
                if (entry != null) {
                    fireRosterPresenceEvent(presence);
                }
            }
            // If an "unavailable" packet.
            else if (presence.getType() == Presence.Type.unavailable) {
                // If no resource, this is likely an offline presence as part of
                // a roster presence flood. In that case, we store it.
                if ("".equals(StringUtils.parseResource(from))) {
                    Map<String, Presence> userPresences;
                    // Get the user presence map
                    if (presenceMap.get(key) == null) {
                        userPresences = new ConcurrentHashMap<String, Presence>();
                        presenceMap.put(key, userPresences);
                    }
                    else {
                        userPresences = presenceMap.get(key);
                    }
                    userPresences.put("", presence);
                }
                // Otherwise, this is a normal offline presence.
                else if (presenceMap.get(key) != null) {
                    Map<String, Presence> userPresences = presenceMap.get(key);
                    // Store the offline presence, as it may include extra information
                    // such as the user being on vacation.
                    userPresences.put(StringUtils.parseResource(from), presence);
                }
                // If the user is in the roster, fire an event.
                RosterEntry entry = entries.get(key);
                if (entry != null) {
                    fireRosterPresenceEvent(presence);
                }
            }
            else if (presence.getType() == Presence.Type.subscribe) {
                if (subscriptionMode == SubscriptionMode.accept_all) {
                    // Accept all subscription requests.
                    Presence response = new Presence(Presence.Type.subscribed);
                    response.setTo(presence.getFrom());
                    connection.sendPacket(response);
                }
                else if (subscriptionMode == SubscriptionMode.reject_all) {
                    // Reject all subscription requests.
                    Presence response = new Presence(Presence.Type.unsubscribed);
                    response.setTo(presence.getFrom());
                    connection.sendPacket(response);
                }
                // Otherwise, in manual mode so ignore.
            }
            else if (presence.getType() == Presence.Type.unsubscribe) {
                if (subscriptionMode != SubscriptionMode.manual) {
                    // Acknowledge and accept unsubscription notification so that the
                    // server will stop sending notifications saying that the contact
                    // has unsubscribed to our presence.
                    Presence response = new Presence(Presence.Type.unsubscribed);
                    response.setTo(presence.getFrom());
                    connection.sendPacket(response);
                }
                // Otherwise, in manual mode so ignore.
            }
            // Error presence packets from a bare JID mean we invalidate all existing
            // presence info for the user.
            else if (presence.getType() == Presence.Type.error &&
                    "".equals(StringUtils.parseResource(from)))
            {
                Map<String, Presence> userPresences;
                if (!presenceMap.containsKey(key)) {
                    userPresences = new ConcurrentHashMap<String, Presence>();
                    presenceMap.put(key, userPresences);
                }
                else {
                    userPresences = presenceMap.get(key);
                    // Any other presence data is invalidated by the error packet.
                    userPresences.clear();
                }
                // Set the new presence using the empty resource as a key.
                userPresences.put("", presence);
                // If the user is in the roster, fire an event.
                RosterEntry entry = entries.get(key);
                if (entry != null) {
                    fireRosterPresenceEvent(presence);
                }
            }
        }
    }
    
    /**
     * Listen for empty IQ results which indicate that the client has already a current
     * roster version
     * @author Till Klocke
     *
     */
    
    private class RosterResultListener implements PacketListener{

		public void processPacket(Packet packet) {
			if(packet instanceof IQ){
				IQ result = (IQ)packet;
				if(result.getType().equals(IQ.Type.RESULT) && result.getExtensions().isEmpty()){
					Collection<String> addedEntries = new ArrayList<String>();
		            Collection<String> updatedEntries = new ArrayList<String>();
		            Collection<String> deletedEntries = new ArrayList<String>();
		            if(persistentStorage!=null){
		            	for(RosterPacket.Item item : persistentStorage.getEntries()){
		            		insertRosterItem(item,addedEntries,updatedEntries,deletedEntries);
		            	}
                            }
		            synchronized (Roster.this) {
		                rosterInitialized = true;
		                Roster.this.notifyAll();
		            }
		            fireRosterChangedEvent(addedEntries,updatedEntries,deletedEntries);
			    }
			}
			connection.removePacketListener(this);
		}
    }

    /**
     * Listens for all roster packets and processes them.
     */
    private class RosterPacketListener implements PacketListener {

        public void processPacket(Packet packet) {
            // Keep a registry of the entries that were added, deleted or updated. An event
            // will be fired for each affected entry
            Collection<String> addedEntries = new ArrayList<String>();
            Collection<String> updatedEntries = new ArrayList<String>();
            Collection<String> deletedEntries = new ArrayList<String>();
           
            String version=null;
            RosterPacket rosterPacket = (RosterPacket) packet;
            List<RosterPacket.Item> rosterItems = new ArrayList<RosterPacket.Item>();
            for(RosterPacket.Item item : rosterPacket.getRosterItems()){
            	rosterItems.add(item);
            }
            //Here we check if the server send a versioned roster, if not we do not use
            //the roster storage to store entries and work like in the old times 
            if(rosterPacket.getVersion()==null){
            	persistentStorage=null;
            } else{
            	version = rosterPacket.getVersion();
            }
            
            if(persistentStorage!=null && !rosterInitialized){
            	for(RosterPacket.Item item : persistentStorage.getEntries()){
            		rosterItems.add(item);
            	}
            }
            
            for (RosterPacket.Item item : rosterItems) {
            	insertRosterItem(item,addedEntries,updatedEntries,deletedEntries);
            }
            if(persistentStorage!=null){
            	for (RosterPacket.Item i : rosterPacket.getRosterItems()){
            		if(i.getItemType().equals(RosterPacket.ItemType.remove)){
            			persistentStorage.removeEntry(i.getUser());
            		}
            		else{
            			persistentStorage.addEntry(i, version);
            		}
            	}
            }
            // Mark the roster as initialized.
            synchronized (Roster.this) {
                rosterInitialized = true;
                Roster.this.notifyAll();
            }

            // Fire event for roster listeners.
            fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
        }
    }
}
