package com.beem.project.beem;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.proxy.ProxyInfo;
import org.jivesoftware.smack.proxy.ProxyInfo.ProxyType;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.beem.project.beem.service.XmppConnectionAdapter;
import com.beem.project.beem.service.XmppFacade;
import com.beem.project.beem.service.aidl.IBeemConnectionListener;
import com.beem.project.beem.service.aidl.IXmppConnection;
import com.beem.project.beem.service.aidl.IXmppFacade;

/**
 * This class is for the Beem service.
 * The connection to the xmpp server will be made asynchronously when the service
 * will start.
 * @author darisk
 */
public class BeemService extends Service {

    /**
     * The id to use for status notification.
     */
    public static final int NOTIFICATION_STATUS_ID = 1;

    private NotificationManager mNotificationManager;
    private XmppConnectionAdapter mConnection;
    private SharedPreferences mSettings;
    private String mLogin;
    private String mPassword;
    private String mHost;
    private ConnectionConfiguration mConnectionConfiguration;
    private ProxyInfo mProxyInfo;
    private boolean mUseProxy;
    private IXmppFacade.Stub mBind;

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

    /**
     * {@inheritDoc}
     */
    @Override
    public IBinder onBind(Intent intent) {
	return mBind;
	// to forbid a client to bind
	// return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate() {
	super.onCreate();
	mSettings = getSharedPreferences(getString(R.string.PreferenceFileName), MODE_PRIVATE);
	mLogin = mSettings.getString(getString(R.string.PreferenceLoginKey), "");
	mPassword = mSettings.getString(getString(R.string.PreferencePasswordKey), "");
	mHost = mSettings.getString(getString(R.string.PreferenceHostKey), "");
	mHost = "10.0.2.2";
	initConnectionConfig();
	mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
	mConnection = new XmppConnectionAdapter(mConnectionConfiguration, mLogin, mPassword);
	initRosterRequestListener();
	mBind = new XmppFacade(mConnection, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onStart(Intent intent, int startId) {
	try {
	    mConnection.connectAsync();
	} catch (RemoteException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDestroy() {
	closeConnection();
	mNotificationManager.cancel(NOTIFICATION_STATUS_ID);
    }

    /**
     * Show a notification.
     * @param id 	the id of the notification.
     * @param notif	the notification to show
     */
    public void sendNotification(int id, Notification notif) {
	mNotificationManager.notify(id, notif);
    }

    /**
     * Initialise la configuration de la connexion.
     */
    private void initConnectionConfig() {
	//TODO mettre a false par defaut et remplacer les valeurs par defaut
	mUseProxy = mSettings.getBoolean(getString(R.string.PreferenceUseProxy), false);
	if (mUseProxy) {
	    String stype = mSettings.getString(getString(R.string.PreferenceProxyType),
		getString(R.string.PreferenceProxyTypeHttp));
	    String phost = mSettings.getString(getString(R.string.PreferenceProxyHost), "");
	    String puser = mSettings.getString(getString(R.string.PreferenceProxyUser), "");
	    String ppass = mSettings.getString(getString(R.string.PreferenceProxyPassword), "");
	    int pport =  mSettings.getInt(getString(R.string.PreferenceProxyPort), 3128);
	    ProxyInfo.ProxyType type = ProxyType.valueOf(stype);
	    mProxyInfo = new ProxyInfo(type, phost, pport, puser, ppass);
	    mConnectionConfiguration = new ConnectionConfiguration(mHost, mProxyInfo);
	} else {
	    mConnectionConfiguration = new ConnectionConfiguration(mHost);
	}
	mConnectionConfiguration.setSendPresence(true);
    }
    
    private void initRosterRequestListener() {
	Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
	final XMPPConnection con =  mConnection.getAdaptee();
	try {
	    mConnection.addConnectionListener(new IBeemConnectionListener.Stub() {
	    
	        @Override
	        public void reconnectionSuccessful() throws RemoteException {
	    	// TODO Auto-generated method stub
	            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;
	    	    }
	    	};
	    	con.addPacketListener(new PacketListener() {
	    	
	    	    @Override
	    	    public void processPacket(Packet packet) {
	    		// TODO Auto-generated method stub
	    		Log.i("TEST", "Une demande recue");
	    	    }
	    	}, filter);
	    	
	        }
	    
	        @Override
	        public void reconnectionFailed() throws RemoteException {
	    	// TODO Auto-generated method stub
	    
	        }
	    
	        @Override
	        public void reconnectingIn(int seconds) throws RemoteException {
	    	// TODO Auto-generated method stub
	    
	        }
	    
	        @Override
	        public void onConnect() throws RemoteException {
	    	// TODO Auto-generated method stub
	            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;
	    	    }
	    	};
	    	con.addPacketListener(new PacketListener() {
	    	
	    	    @Override
	    	    public void processPacket(Packet packet) {
	    		// TODO Auto-generated method stub
	    		Log.i("TEST", "Une demande recue");
	    	    }
	    	}, filter);
	    	
	        }
	    
	        @Override
	        public void connectionClosedOnError() throws RemoteException {
	    	// TODO Auto-generated method stub
	    
	        }
	    
	        @Override
	        public void connectionClosed() throws RemoteException {
	    	// TODO Auto-generated method stub
	    
	        }
	    });
	} catch (RemoteException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}
	
    }

    /**
     * Close the connection to the xmpp server.
     */
    private void closeConnection() {
	if (mConnection != null)
	    mConnection.disconnect();
    }

}
