package com.beem.project.beem;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.proxy.ProxyInfo;
import org.jivesoftware.smack.proxy.ProxyInfo.ProxyType;
import org.jivesoftware.smack.util.StringUtils;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.IBinder;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.util.Log;

import com.beem.project.beem.jingle.JingleService;
import com.beem.project.beem.service.XmppConnectionAdapter;
import com.beem.project.beem.service.XmppFacade;
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 = 100;
    private static final int DEFAULT_XMPP_PORT = 5222;

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

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

    /**
     * Initialise la configuration de la connexion.
     */
    private void initConnectionConfig() {
	java.security.Security.addProvider(new com.sun.security.sasl.Provider());
	mUseProxy = mSettings.getBoolean("settings_key_proxy_use", false);
	if (mUseProxy) {
	    String stype = mSettings.getString("settings_key_proxy_type", "HTTP");
	    String phost = mSettings.getString("settings_key_proxy_server", "");
	    String puser = mSettings.getString("settings_key_proxy_username", "");
	    String ppass = mSettings.getString("settings_key_proxy_password", "");
	    int pport = Integer.parseInt(mSettings.getString("settings_key_proxy_port", "1080"));
	    ProxyInfo.ProxyType type = ProxyType.valueOf(stype);
	    mProxyInfo = new ProxyInfo(type, phost, pport, puser, ppass);
	    if (mService != null)
		mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort, mService, mProxyInfo);
	    else
		mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort, mProxyInfo);
	} else {
	    if (mService != null)
		mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort, mService);
	    else
		mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort);
	}
	if (mSettings.getBoolean("settings_key_xmpp_tls_use", false)
	    || mSettings.getBoolean("settings_key_gmail", false)) {
	    mConnectionConfiguration.setSecurityMode(SecurityMode.required);
	}
	mConnectionConfiguration.setDebuggerEnabled(false);
	mConnectionConfiguration.setSendPresence(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IBinder onBind(Intent intent) {
	Log.d("BEEMSERVICE", "ONBIND()");
	return mBind;
    }

    @Override
    public boolean onUnbind(Intent intent) {
	Log.d("BEEMSERVICE", "ONUNBIND()");
	if (!mConnection.getAdaptee().isConnected()) {
	    Log.d("BEEMSERVICE", "DESTROYED");
	    this.stopSelf();
	}
	return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate() {

	super.onCreate();
	mSettings = PreferenceManager.getDefaultSharedPreferences(this);
	String tmpJid = mSettings.getString("settings_key_account_username", "");
	mLogin = StringUtils.parseName(tmpJid);
	mPassword = mSettings.getString("settings_key_account_password", "");
	mPort = DEFAULT_XMPP_PORT;
	mService = StringUtils.parseServer(tmpJid);
	mHost = StringUtils.parseServer(tmpJid);

	if (mSettings.getBoolean("settings_key_specific_server", false)) {
	    mHost = mSettings.getString("settings_key_xmpp_server", "");
	    mPort = Integer.parseInt(mSettings.getString("settings_key_xmpp_port", "5222"));
	}
	if (mSettings.getBoolean("settings_key_gmail", false)) {
	    mHost = "talk.google.com";
	    mLogin = tmpJid;
	}

	initConnectionConfig();
	mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
	mConnection = new XmppConnectionAdapter(mConnectionConfiguration, mLogin, mPassword, this);

	Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
	mJingle = new JingleService(mConnection.getAdaptee());
	mBind = new XmppFacade(mConnection, this, mJingle);
	Log.d("BEEEMSERVICE", "ONCREATE");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDestroy() {
	super.onDestroy();
	mNotificationManager.cancel(NOTIFICATION_STATUS_ID);
	if (mConnection.isAuthentificated())
	    mConnection.disconnect();
	Log.d("BEEEMSERVICE", "ONDESTROY");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onStart(Intent intent, int startId) {
	super.onStart(intent, startId);
	Log.d("BEEMSERVICE", "onStart");
	try {
	    mConnection.connectAsync();
	} catch (RemoteException e) {
	    e.printStackTrace();
	}
    }

    /**
     * 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);
    }

    /**
     * Delete a notification.
     * @param id the id of the notification
     */
    public void deleteNotification(int id) {
	mNotificationManager.cancel(id);
    }

    /**
     * Reset the status to online after a deconnection.
     */
    public void resetStatus() {
	Editor edit = mSettings.edit();
	edit.putInt(getString(R.string.PreferenceStatus), 1);
	edit.commit();
    }

    /**
     * init jingle from XmppConnectionAdapter.
     * @param adaptee XmppConntection used for jingle.
     */
    public void initJingle(XMPPConnection adaptee) {
	mJingle.initWhenConntected(adaptee);
    }
    
    public IXmppFacade getBind() {
	return mBind;
    }
}
