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

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;

import android.os.RemoteCallbackList;
import android.os.RemoteException;

import com.beem.project.beem.BeemException;
import com.beem.project.beem.service.aidl.IBeemConnectionListener;
import com.beem.project.beem.service.aidl.IRoster;
import com.beem.project.beem.service.aidl.IXMPPConnection;

/**
 * @author darisk
 * 
 */
public class XMPPConnectionAdapter extends IXMPPConnection.Stub {

    private XMPPConnection adaptee;
    private BeemException lastException;

    private RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners = new RemoteCallbackList<IBeemConnectionListener>();
    private ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();
    
    public XMPPConnectionAdapter(XMPPConnection con) {
	adaptee = con;
    }

    public XMPPConnectionAdapter(String serviceName) {
	this(new XMPPConnection(serviceName));
    }

    public XMPPConnectionAdapter(ConnectionConfiguration config) {
	this(new XMPPConnection(config));
    }

    @Override
    public boolean connectSync(String username, String password, String resource)
            throws RemoteException {
     	try {
	    adaptee.connect();
	    adaptee.addConnectionListener(mConListener);
	    adaptee.login(username, password, resource);
	    lastException = null;
	    triggerAsynchronousConnectEvent();
	    return true;
	} catch (XMPPException e) {
	    lastException = new BeemException(e);
	}
	return false;
    }

    public boolean disconnect() {
	adaptee.disconnect();
	lastException = null;
	return true;
    }

    @Override
    public IRoster getRoster() throws RemoteException {
	return new RosterAdapter(adaptee.getRoster());
    }

    @Override
    public void connectAsync(final String username, final String password, final String resource)
            throws RemoteException {
	Thread t = new Thread(new Runnable() {

	    @Override
	    public void run() {
		try {
		    connectSync(username,password,resource);
		} catch (RemoteException e) {
		   
		}
	    }
	});
	t.start();
    }

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

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

    private void triggerAsynchronousConnectEvent() {
	mConListener.onConnect();
    }
  
    private class ConnexionListenerAdapter implements ConnectionListener {

	public void onConnect() {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.onConnect();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}
	
	@Override
	public void connectionClosed() {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.connectionClosed();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	@Override
	public void connectionClosedOnError(Exception arg0) {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.connectionClosedOnError();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	@Override
	public void reconnectingIn(int arg0) {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.reconnectingIn(arg0);
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	@Override
	public void reconnectionFailed(Exception arg0) {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.reconnectionFailed();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}

	@Override
	public void reconnectionSuccessful() {
	    final int N = mRemoteConnListeners.beginBroadcast();

	    for (int i = 0; i < N; i++) {
		IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
		try {
		    listener.reconnectionSuccessful();
		} catch (RemoteException e) {
		    // The RemoteCallbackList will take care of removing the
		    // dead listeners.
		}
	    }
	    mRemoteConnListeners.finishBroadcast();
	}	
    }
    

}
