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

import java.util.LinkedList;
import java.util.List;

import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import com.beem.project.beem.service.aidl.IXMPPFacade;

/**
 * The Beem application.
 * This class has some methods utiliy needs by the activities.
 * @author darisk
 */
public class BeemApplication extends Application {

    private static BeemApplication mBeemApp;
    private IXMPPFacade mFacade;

    private Context mApplicationContext;
    private Resources mPrivateResources;
    private List<Message> mQueue = new LinkedList<Message>();
    private boolean mIsConnected;



    private ServiceConnection mServConn = new ServiceConnection() {

	@Override
	public void onServiceDisconnected(ComponentName name) {
	    mFacade = null;
	    mIsConnected = false;
	}

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
	    // TODO Auto-generated method stub
	    mFacade = IXMPPFacade.Stub.asInterface(service);
	    synchronized (mQueue) {
		for (Message msg : mQueue) {
		    msg.sendToTarget();
		}
		mQueue.clear();
	    }
	}
    };

    /**
     * Constructor.
     */
    public BeemApplication() {
	// TODO Auto-generated constructor stub
    }

    /**
     * Get the Beem application for an activity.
     * @param activity	the activity which want the Beem application
     * @return		the Beem application
     */
    public static BeemApplication getApplication(Activity activity) {
	if (mBeemApp == null) {
	    mBeemApp = new BeemApplication();
	    mBeemApp.mApplicationContext = activity.getApplication();
	    mBeemApp.mPrivateResources = activity.getResources();
	    mBeemApp.onCreate();
	}
	return mBeemApp;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
	// TODO Auto-generated method stub
	super.onConfigurationChanged(newConfig);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate() {
	// TODO Auto-generated method stub
	super.onCreate();
	mFacade = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onLowMemory() {
	// TODO Auto-generated method stub
	super.onLowMemory();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onTerminate() {
	// TODO Auto-generated method stub
	super.onTerminate();
    }

    /**
     * Start the beem service.
     */
    public synchronized void startBeemService() {
	if (!mIsConnected) {
	    // Intent intent = new Intent(this, BeemService.class);
	    Intent intent = new Intent();
	    intent.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
	    mApplicationContext.startService(intent);
	    mApplicationContext.bindService(intent, mServConn, BIND_AUTO_CREATE);
	    mIsConnected = true;
	}
    }

    /**
     * Stop the Beem service.
     */
    public synchronized void stopBeemService() {
	if (mIsConnected) {
	    Intent intent = new Intent();
	    intent.setComponent(new ComponentName("com.beem.project.beem",
		    "com.beem.project.beem.BeemService"));
	    mApplicationContext.unbindService(mServConn);
	    mApplicationContext.stopService(intent);
	    mIsConnected = false;
	}
    }

    /**
     * Get the facade to use to access the Beem service.
     * @return	the facade or null if the application is not connected to the beem service.
     */
    public IXMPPFacade getXmppFacade() {
	return mFacade;
    }


    /**
     * Add a methode to execute when the application is connected to the Beem service.
     * @param target	the handler which will execute the callback
     * @param callback	the callback to execute
     */
    public void callWhenServiceConnected(Handler target, Runnable callback) {
	Message msg = Message.obtain(target, callback);
	if (!mIsConnected) {
	    msg.sendToTarget();
	} else {
	    startBeemService();
	    synchronized (mQueue) {
		mQueue.add(msg);
	    }
	}
    }

    /**
     * Indique si on est connecte au service.
     */
    public boolean isConnected() {
	return mIsConnected;
    }

}
