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