/*
    BEEM is a videoconference application on the Android Platform.

    Copyright (C) 2009 by Frederic-Charles Barthelery,
                          Jean-Manuel Da Silva,
                          Nikita Kozlov,
                          Philippe Lago,
                          Jean Baptiste Vergely,
                          Vincent Veronis.

    This file is part of BEEM.

    BEEM is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BEEM is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.

    Please send bug reports with examples or suggestions to
    contact@beem-project.com or http://dev.beem-project.com/

    Epitech, hereby disclaims all copyright interest in the program "Beem"
    written by Frederic-Charles Barthelery,
               Jean-Manuel Da Silva,
               Nikita Kozlov,
               Philippe Lago,
               Jean Baptiste Vergely,
               Vincent Veronis.

    Nicolas Sadirac, November 26, 2009
    President of Epitech.

    Flavien Astraud, November 26, 2009
    Head of the EIP Laboratory.

 */
package com.beem.project.beem.service;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.PrivacyListManager;
import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.ChatStateManager;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.packet.DiscoverInfo;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import com.beem.project.beem.BeemApplication;
import com.beem.project.beem.BeemIntent;
import com.beem.project.beem.BeemService;
import com.beem.project.beem.R;
import com.beem.project.beem.providers.Messages;
import com.beem.project.beem.service.aidl.IBeemConnectionListener;
import com.beem.project.beem.service.aidl.IXmppConnection;
import com.beem.project.beem.smack.avatar.AvatarCache;
import com.beem.project.beem.smack.avatar.AvatarManager;
import com.beem.project.beem.smack.pep.PepSubManager;
import com.beem.project.beem.ui.Subscription;
import com.beem.project.beem.utils.BeemBroadcastReceiver;
import com.beem.project.beem.utils.Status;

/**
 * This class implements an adapter for XMPPConnection.
 * @author darisk
 */
public class XmppConnectionAdapter extends IXmppConnection.Stub {

    /**
     * Beem connection closed Intent name.
     */

    private static final int SMACK_PRIORITY_MIN = -128;
    private static final int SMACK_PRIORITY_MAX = 128;
    private static final String TAG = "XMPPConnectionAdapter";
    private final XMPPConnection mAdaptee;
    private final String mLogin;
    private final String mPassword;
    private String mResource;
    private String mErrorMsg;
    private int mPreviousPriority;
    private int mPreviousMode;
    private String mPreviousStatus;
    private ChatStateManager mChatStateManager;
    private final BeemService mService;
    private BeemApplication mApplication;
    private AvatarManager mAvatarManager;
    private PepSubManager mPepManager;
    private SharedPreferences mPref;
    private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners = new RemoteCallbackList<IBeemConnectionListener>();
    private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener();

    //private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();

    /**
     * Constructor.
     * @param config Configuration to use in order to connect
     * @param login login to use on connect
     * @param password password to use on connect
     * @param service the background service associated with the connection.
     */
    public XmppConnectionAdapter(final ConnectionConfiguration config, final String login, final String password,
	final BeemService service) {
	this(new XMPPConnection(config), login, password, service);
    }

    /**
     * Constructor.
     * @param serviceName name of the service to connect to
     * @param login login to use on connect
     * @param password password to use on connect
     * @param service the background service associated with the connection.
     */
    public XmppConnectionAdapter(final String serviceName, final String login, final String password,
	final BeemService service) {
	this(new XMPPConnection(serviceName), login, password, service);
    }

    /**
     * Constructor.
     * @param con The connection to adapt
     * @param login The login to use
     * @param password The password to use
     * @param service the background service associated with the connection.
     */
    public XmppConnectionAdapter(final XMPPConnection con, final String login, final String password,
	final BeemService service) {
	mAdaptee = con;
	PrivacyListManager.getInstanceFor(mAdaptee);
	mLogin = StringUtils.parseName(login);

	mPassword = password;
	mService = service;
	Context ctx = mService.getApplicationContext();
	if (ctx instanceof BeemApplication) {
	    mApplication = (BeemApplication) ctx;
	}
	mPref = mService.getServicePreference(login); // login is the jid
	try {
	    mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0"));
	} catch (NumberFormatException ex) {
	    mPreviousPriority = 0;
	}
	mResource = mPref.getString("settings_key_resource", "BEEM");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException {
	if (listen != null)
	    mRemoteConnListeners.register(listen);
    }

    @Override
    public boolean connect() throws RemoteException {
	if (mAdaptee.isConnected())
	    return true;
	else {
	    try {
		mAdaptee.connect();
		//mAdaptee.addConnectionListener(mConListener);
		return true;
	    } catch (XMPPException e) {
		Log.e(TAG, "Error while connecting", e);
		try {
		    //TODO NIKITA DOES SOME SHIT !!! Fix this monstruosity
		    String str = mService.getResources().getString(
			mService.getResources().getIdentifier(e.getXMPPError().getCondition().replace("-", "_"),
			    "string", "com.beem.project.beem"));
		    mErrorMsg = str;
		} catch (NullPointerException e2) {
		    if (!"".equals(e.getMessage()))
			mErrorMsg = e.getMessage();
		    else
			mErrorMsg = e.toString();
		}
	    }
	    return false;
	}
    }

    @Override
    public boolean login() throws RemoteException {
	if (mAdaptee.isAuthenticated())
	    return true;
	if (!mAdaptee.isConnected())
	    return false;
	try {

	    this.initFeatures(); // pour declarer les features xmpp qu'on
	    // supporte

	    PacketFilter filter = new PacketFilter() {

		@Override
		public boolean accept(Packet packet) {
		    if (packet instanceof Presence) {
			Presence pres = (Presence) packet;
			if (pres.getType() == Presence.Type.subscribe)
			    return true;
		    } else if (packet instanceof Message) {
			return true;
		    }
		    return false;
		}
	    };

	    mAdaptee.addPacketListener(mSubscribePacketListener, filter);
	    Log.e(TAG, mLogin + mPassword + mResource);
	    mAdaptee.login(mLogin, mPassword, mResource);
	    //mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService);
	    //nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321
	    //Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it
	    //mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee));
	    mService.initJingle(mAdaptee);
	    discoverServerFeatures();

	    mAdaptee.getRoster().addRosterListener(new SubscribeRosterListener());

	    mApplication.setConnected(true);
	    int mode = mPref.getInt(BeemApplication.STATUS_KEY, 0);
	    String status = mPref.getString(BeemApplication.STATUS_TEXT_KEY, "");
	    changeStatus(mode, status);
	    return true;
	} catch (XMPPException e) {
	    Log.e(TAG, "Error while connecting", e);
	    mErrorMsg = mService.getString(R.string.error_login_authentication);
	    return false;
	}
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void connectAsync() throws RemoteException {
	if (mAdaptee.isConnected() || mAdaptee.isAuthenticated())
	    return;
	Thread t = new Thread(new Runnable() {

	    @Override
	    public void run() {
		try {
		    connectSync();
		} catch (RemoteException e) {
		    Log.e(TAG, "Error while connecting asynchronously", e);
		}
	    }
	});
	t.start();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connectSync() throws RemoteException {
	if (connect())
	    return login();
	return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void changeStatusAndPriority(int status, String msg, int priority) {
	Presence pres = new Presence(Presence.Type.available);
	String m;
	if (msg != null)
	    m = msg;
	else
	    m = mPreviousStatus;
	pres.setStatus(m);
	mPreviousStatus = m;
	Presence.Mode mode = Status.getPresenceModeFromStatus(status);
	if (mode != null) {
	    pres.setMode(mode);
	    mPreviousMode = status;
	} else {
	    pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode));
	}
	int p = priority;
	if (priority < SMACK_PRIORITY_MIN)
	    p = SMACK_PRIORITY_MIN;
	if (priority > SMACK_PRIORITY_MAX)
	    p = SMACK_PRIORITY_MAX;
	mPreviousPriority = p;
	pres.setPriority(p);
	mAdaptee.sendPacket(pres);
	updateNotification(m);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void changeStatus(int status, String msg) {
	changeStatusAndPriority(status, msg, mPreviousPriority);
    }

    /**
     * Get the AvatarManager of this connection.
     * @return the AvatarManager or null if there is not
     */
    public AvatarManager getAvatarManager() {
	return mAvatarManager;
    }

    /**
     * get the previous status.
     * @return previous status.
     */
    public String getPreviousStatus() {
	return mPreviousStatus;
    }

    /**
     * get the previous mode.
     * @return previous mode.
     */
    public int getPreviousMode() {
	return mPreviousMode;
    }

    /**
     * Update the notification for the Beem status.
     * @param text the text to display.
     */
    private void updateNotification(String text) {

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean disconnect() {
	if (mAdaptee != null && mAdaptee.isConnected())
	    mAdaptee.disconnect();
	return true;
    }

    /**
     * Get the Smack XmppConnection.
     * @return Smack XmppConnection
     */
    public XMPPConnection getAdaptee() {
	return mAdaptee;
    }

    /**
     * Returns true if currently authenticated by successfully calling the login method.
     * @return true when successfully authenticated
     */
    public boolean isAuthentificated() {
	return mAdaptee.isAuthenticated();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException {
	if (listen != null)
	    mRemoteConnListeners.unregister(listen);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getErrorMessage() {
	return mErrorMsg;
    }

    public void handleMessage(String accountName, android.os.Message msg) {
	Log.e(TAG, "HANDLEMESSAGE");

	Bundle b = (Bundle) msg.obj;
	String to = b.getString(BeemIntent.EXTRA_JID);
	String body = b.getString(BeemIntent.EXTRA_MESSAGE);

	Message send = new Message();
	send.setFrom(accountName);
	send.setThread(""); //TODO: set ThreadID
	send.setTo(to);
	send.setBody(body);
	send.setType(Message.Type.chat);
	// TODO gerer les messages contenant des XMPPError
	try {
	    mAdaptee.sendPacket(send);
	} catch (IllegalStateException e) {
	    Log.e(TAG, "Message not send", e);
	}
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	ContentValues values = new ContentValues();
	values.put(Messages.FROM, "me"); //TODO: Get current account name
	values.put(Messages.MESSAGE_ID, "message id");
	values.put(Messages.TO, to);
	values.put(Messages.TYPE, Message.Type.chat.toString());
	values.put(Messages.SUBJECT, "SUBJECT");
	values.put(Messages.BODY, body);
	values.put(Messages.THREAD, "");
	values.put(Messages.EXTRAS, "");
	values.put(Messages.IS_RECEIVE, true);
	values.put(Messages.DATE_RECEIVE, dateFormat.format(new Date()));
	values.put(Messages.DATE_READ, dateFormat.format(new Date()));
	mService.getContentResolver().insert(Messages.CONTENT_URI, values);

    }

    /**
     * Initialize the features provided by beem.
     */
    private void initFeatures() {
	ServiceDiscoveryManager.setIdentityName("Beem");
	ServiceDiscoveryManager.setIdentityType("phone");
	ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
	if (sdm == null)
	    sdm = new ServiceDiscoveryManager(mAdaptee);

	sdm.addFeature("http://jabber.org/protocol/disco#info");
	//nikita: must be uncommented when the feature will be enabled
	//sdm.addFeature("jabber:iq:privacy");
	sdm.addFeature("http://jabber.org/protocol/caps");
	sdm.addFeature("urn:xmpp:avatar:metadata");
	sdm.addFeature("urn:xmpp:avatar:metadata+notify");
	sdm.addFeature("urn:xmpp:avatar:data");
	sdm.addFeature("http://jabber.org/protocol/nick");
	sdm.addFeature("http://jabber.org/protocol/nick+notify");

	mChatStateManager = ChatStateManager.getInstance(mAdaptee);
	BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService);
	caps.setNode("http://www.beem-project.com");
    }

    /**
     * Discover the features provided by the server.
     */
    private void discoverServerFeatures() {
	try {
	    // jid et server
	    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
	    DiscoverInfo info = sdm.discoverInfo(mAdaptee.getServiceName());
	    Iterator<DiscoverInfo.Identity> it = info.getIdentities();
	    while (it.hasNext()) {
		DiscoverInfo.Identity identity = it.next();
		if ("pubsub".equals(identity.getCategory()) && "pep".equals(identity.getType())) {
		    initPEP();
		}
	    }
	} catch (XMPPException e) {
	    // No Pep
	}
    }

    /**
     * Initialize PEP.
     */
    private void initPEP() {
	// Enable pep sending
	// API 8
	// mService.getExternalCacheDir()
	mPepManager = new PepSubManager(mAdaptee);
	AvatarCache avatarCache = new BeemAvatarCache(mService);
	mAvatarManager = new AvatarManager(mAdaptee, mPepManager, avatarCache, true);
    }

    /**
     * Listener for XMPP connection events. It will calls the remote listeners for connection events.
     * @author darisk
     */
    private class ConnexionListenerAdapter implements ConnectionListener {

	/**
	 * Defaut constructor.
	 */
	public ConnexionListenerAdapter() {
	}

	/**
	 * {@inheritDoc}
	 */
	/**
	 * // * Listener. //
	 */
	//	    private class MsgListener implements ChatStateListener {
	//		/**
	//		 * Constructor.
	//		 */
	//		public MsgListener() {
	//		}
	//
	//		@Override
	//		public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
	//		    Message msg = new Message(message);
	//		    Log.e(TAG, "Message : " + msg.getBody());
	//		    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	//		    // note that we don't have to add an id as our table set id as autoincrement
	//		    ContentValues values = new ContentValues();
	//		    values.put(Messages.FROM, msg.getFrom());
	//		    values.put(Messages.MESSAGE_ID, "message id");
	//		    values.put(Messages.TO, msg.getTo());
	//		    values.put(Messages.TYPE, msg.getType());
	//		    values.put(Messages.SUBJECT, "SUBJECT");
	//		    values.put(Messages.BODY, msg.getBody());
	//		    values.put(Messages.THREAD, "THREAD");
	//		    values.put(Messages.EXTRAS, "EXTRAS");
	//		    values.put(Messages.IS_RECEIVE, true);
	//		    values.put(Messages.DATE_RECEIVE, dateFormat.format(new Date()));
	//		    values.put(Messages.DATE_READ, dateFormat.format(msg.getTimestamp()));
	//		    mService.getContentResolver().insert(Messages.CONTENT_URI, values);
	//		}
	//
	//		/**
	//		 * {@inheritDoc}
	//		 */
	//		@Override
	//		public void stateChanged(Chat chat, ChatState state) {
	//		}
	//
	//	    }
	@Override
	public void connectionClosed() {
	    Log.d(TAG, "closing connection");
	    Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
	    intent.putExtra("message", mService.getString(R.string.BeemBroadcastReceiverDisconnect));
	    intent.putExtra("normally", true);
	    mService.sendBroadcast(intent);
	    mService.stopSelf();
	    mApplication.setConnected(false);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void connectionClosedOnError(Exception exception) {
	    Log.d(TAG, "connectionClosedOnError");
	    Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED);
	    intent.putExtra("message", exception.getMessage());
	    mService.sendBroadcast(intent);
	    mService.stopSelf();
	    mApplication.setConnected(false);
	}

	/**
	 * Connection failed callback.
	 * @param errorMsg smack failure message
	 */
	public void connectionFailed(String errorMsg) {
	    Log.d(TAG, "Connection Failed");
	    final int n = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < n; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    if (listener != null)
			listener.connectionFailed(errorMsg);
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		    Log.w(TAG, "Error while triggering remote connection listeners", e);
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	    mService.stopSelf();
	    mApplication.setConnected(false);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void reconnectingIn(int arg0) {
	    Log.d(TAG, "reconnectingIn");
	    final int n = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < n; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    if (listener != null)
			listener.reconnectingIn(arg0);
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		    Log.w(TAG, "Error while triggering remote connection listeners", e);
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void reconnectionFailed(Exception arg0) {
	    Log.d(TAG, "reconnectionFailed");
	    final int r = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < r; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    if (listener != null)
			listener.reconnectionFailed();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		    Log.w(TAG, "Error while triggering remote connection listeners", e);
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void reconnectionSuccessful() {
	    Log.d(TAG, "reconnectionSuccessful");
	    mApplication.setConnected(true);
	    PacketFilter filter = new PacketFilter() {

		@Override
		public boolean accept(Packet packet) {
		    if (packet instanceof Presence) {
			Presence pres = (Presence) packet;
			if (pres.getType() == Presence.Type.subscribe)
			    return true;
		    }
		    return false;
		}
	    };

	    mAdaptee.addPacketListener(new PacketListener() {

		@Override
		public void processPacket(Packet packet) {
		    String from = packet.getFrom();
		    Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString(
			R.string.AcceptContactRequest, from), System.currentTimeMillis());
		    notif.flags = Notification.FLAG_AUTO_CANCEL;
		    Intent intent = new Intent(mService, Subscription.class);
		    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("from", from);
		    notif.setLatestEventInfo(mService, from,
			mService.getString(R.string.AcceptContactRequestFrom, from),
			PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT));
		    int id = packet.hashCode();
		    mService.sendNotification(id, notif);
		}
	    }, filter);

	    final int n = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < n; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    if (listener != null)
			listener.reconnectionSuccessful();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		    Log.w(TAG, "Error while triggering remote connection listeners", e);
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}
    }

    /**
     * This PacketListener will set a notification when you got a subscribtion request.
     * @author Da Risk <da_risk@elyzion.net>
     */
    private class SubscribePacketListener implements PacketListener {

	/**
	 * Constructor.
	 */
	public SubscribePacketListener() {
	}

	@Override
	public void processPacket(Packet packet) {
	    Log.e(TAG, "Message : " + packet.getClass().toString());
	    if (packet instanceof Presence) {
		Presence p = (Presence) packet;
		if (p.getType() != Presence.Type.subscribe)
		    return;
		String from = p.getFrom();
		Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString(
		    R.string.AcceptContactRequest, from), System.currentTimeMillis());
		notification.flags = Notification.FLAG_AUTO_CANCEL;
		Intent intent = new Intent(mService, Subscription.class);
		intent.setData(makeXmppUri(from));
		notification.setLatestEventInfo(mService, from,
		    mService.getString(R.string.AcceptContactRequestFrom, from),
		    PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT));
		int id = p.hashCode();
		mService.sendNotification(id, notification);
	    } else if (packet instanceof Message) {
		Message message = (Message) packet;

		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		// note that we don't have to add an id as our table set id as autoincrement
		ContentValues values = new ContentValues();
		values.put(Messages.FROM, message.getFrom());
		values.put(Messages.MESSAGE_ID, "message id");
		values.put(Messages.TO, message.getTo());
		values.put(Messages.TYPE, message.getType().toString());
		values.put(Messages.SUBJECT, "SUBJECT");
		values.put(Messages.BODY, message.getBody());
		values.put(Messages.THREAD, message.getThread());
		values.put(Messages.EXTRAS, "");
		values.put(Messages.IS_RECEIVE, true);
		values.put(Messages.DATE_RECEIVE, dateFormat.format(new Date()));
		values.put(Messages.DATE_READ, dateFormat.format(new Date()));
		mService.getContentResolver().insert(Messages.CONTENT_URI, values);
	    }
	}
    }

    private class SubscribeRosterListener implements RosterListener {

	@Override
	public void entriesAdded(Collection<String> addresses) {
	    Log.e(TAG, "entriesAdded");
	}

	@Override
	public void entriesUpdated(Collection<String> addresses) {
	    Log.e(TAG, "entriesUpdated");
	}

	@Override
	public void entriesDeleted(Collection<String> addresses) {
	    Log.e(TAG, "entriesDeleted");
	}

	@Override
	public void presenceChanged(Presence presence) {
	    Log.e(TAG, "presenceChanged");
	}

    }

    /**
     * Make an xmpp uri for a spcific jid.
     * @param jid the jid to represent as an uri
     * @return an uri representing this jid.
     */
    public static Uri makeXmppUri(String jid) {
	StringBuilder build = new StringBuilder("xmpp:");
	String name = StringUtils.parseName(jid);
	build.append(name);
	if (!"".equals(name))
	    build.append('@');
	build.append(StringUtils.parseServer(jid));
	String resource = StringUtils.parseResource(jid);
	if (!"".equals(resource)) {
	    build.append('/');
	    build.append(resource);
	}
	Uri u = Uri.parse(build.toString());
	return u;
    }

}
