package com.beem.project.beem.ui;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;

import com.beem.project.beem.BeemService;
import com.beem.project.beem.R;
import com.beem.project.beem.service.PrivacyListItem;
import com.beem.project.beem.service.aidl.IPrivacyListListener;
import com.beem.project.beem.service.aidl.IPrivacyListManager;
import com.beem.project.beem.service.aidl.IXmppFacade;
import com.beem.project.beem.utils.BeemBroadcastReceiver;

/**
 * This class represents an activity which allows the user to manage his privacy lists.
 * @author Jean-Manuel Da Silva <dasilvj at beem-project dot com>
 */
public class PrivacyList extends ListActivity {

    private static final String TAG = "PrivacyList";
    private static final Intent SERVICE_INTENT = new Intent();
    static {
	SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
    }
    private static final int DIALOG_PRIVACY_LIST_ITEM = 1;
    private static final int DIALOG_CREATE_PRIVACY_LIST = 2;

    private static final String SAVED_INSTANCE_KEY_PRIVACY_LISTS = "PRIVACY_LISTS";
    private static final String SAVED_INSTANCE_KEY_LAST_CLICKED_ITEM = "LAST_CLICKED_ITEM";

    private Handler mHandler = new Handler();

    private ArrayAdapter<String> mAdapter;
    private final List<String> mPrivacyListNames = new ArrayList<String>();
    private int mPosLastClickedItem;

    private final ServiceConnection mConn = new BeemServiceConnection();
    private BeemBroadcastReceiver mBroadcastReceiver;

    private IPrivacyListManager mPrivacyListManager;
    private IPrivacyListListener mPrivacyListListener;

    /**
     * Constructor.
     */
    public PrivacyList() {
	super();
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
	Log.d(TAG, "BEGIN onSaveInstanceState.");
	savedInstanceState.putStringArrayList(SAVED_INSTANCE_KEY_PRIVACY_LISTS, (ArrayList<String>) mPrivacyListNames);
	savedInstanceState.putInt(SAVED_INSTANCE_KEY_LAST_CLICKED_ITEM, mPosLastClickedItem);
	Log.d(TAG, "END onSaveInstanceState.");
	super.onSaveInstanceState(savedInstanceState);
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	Log.d(TAG, "BEGIN onCreate.");
	setContentView(R.layout.privacy_list);

	mHandler = new Handler();

	if (savedInstanceState != null && !savedInstanceState.isEmpty()) {
	    mPrivacyListNames.addAll(savedInstanceState.getStringArrayList(SAVED_INSTANCE_KEY_PRIVACY_LISTS));
	    mPosLastClickedItem = savedInstanceState.getInt(SAVED_INSTANCE_KEY_LAST_CLICKED_ITEM);
	}

	mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mPrivacyListNames);
	setListAdapter(mAdapter);

	mPrivacyListListener = new PrivacyListListener();
	mBroadcastReceiver = new BeemBroadcastReceiver(mConn);
	this.registerReceiver(mBroadcastReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));

	Log.d(TAG, "END onCreate.");
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
	Log.d(TAG, "BEGIN onPrepareDialog.");
	switch (id) {
	    case DIALOG_PRIVACY_LIST_ITEM:
		String dialogTitle = (mPosLastClickedItem > mPrivacyListNames.size() ? "" : mPrivacyListNames
		    .get(mPosLastClickedItem));
		dialog.setTitle(dialogTitle);
	}
	Log.d(TAG, "END onPrepareDialog.");
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected Dialog onCreateDialog(int id) {
	Log.d(TAG, "BEGIN onCreateDialog.");
	switch (id) {
	    case DIALOG_PRIVACY_LIST_ITEM:
		return new AlertDialog.Builder(this).setTitle("X").setItems(R.array.privacy_list_select_dialog,
		    new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
			    String[] items = getResources().getStringArray(R.array.privacy_list_select_dialog);
			    if (items[which].equals(getResources().getString(
				R.string.privacy_list_select_dialog_delete))) {
				try {
				    mPrivacyListManager.removePrivacyList(mPrivacyListNames.get(mPosLastClickedItem));
				} catch (RemoteException e) {
				    Log.e(TAG, e.getMessage());
				}
				dismissDialog(DIALOG_PRIVACY_LIST_ITEM);
			    }
			}
		    }).create();

	    case DIALOG_CREATE_PRIVACY_LIST:
		LayoutInflater factory = LayoutInflater.from(this);
		final View textEntryView = factory.inflate(R.layout.privacy_list_create_dialog, null);

		return new AlertDialog.Builder(this).setTitle(R.string.privacy_list_create_dialog_title).setView(
		    textEntryView).setPositiveButton(R.string.privacy_list_create_dialog_create_button,
		    new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
			    EditText listNameField = (EditText) textEntryView
				.findViewById(R.id.privacy_list_create_dialog_list_name);
			    try {
				mPrivacyListManager.createPrivacyList(listNameField.getText().toString(),
				    new ArrayList<PrivacyListItem>());
			    } catch (RemoteException e) {
				Log.e(TAG, e.getMessage());
			    }
			}
		    }).setNegativeButton(R.string.CancelButton, new DialogInterface.OnClickListener() {
		    public void onClick(DialogInterface dialog, int whichButton) {
		    }
		}).create();
	}
	Log.d(TAG, "END onCreateDialog.");
	return null;
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onDestroy() {
	super.onDestroy();

	Log.v(TAG, "BEGIN onDestroy.");
	this.unregisterReceiver(mBroadcastReceiver);
	if (mPrivacyListManager != null) {
	    try {
		mPrivacyListManager.removePrivacyListListener(mPrivacyListListener);
	    } catch (RemoteException e) {
		Log.e(TAG, e.getMessage());
	    }
	}
	Log.v(TAG, "END onDestroy.");
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onStart() {
	super.onStart();

	Log.v(TAG, "BEGIN onStart.");
	bindService(new Intent(this, BeemService.class), mConn, BIND_AUTO_CREATE);
	Log.v(TAG, "END onStart.");
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    protected void onStop() {
	super.onStop();

	Log.v(TAG, "BEGIN onStop.");
	if (mBroadcastReceiver.isBinded()) {
	    unbindService(mConn);
	}
	Log.v(TAG, "END onStop.");
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    public final boolean onCreateOptionsMenu(Menu menu) {
	super.onCreateOptionsMenu(menu);

	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.privacy_list, menu);
	return true;
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
	mPosLastClickedItem = position;
	showDialog(DIALOG_PRIVACY_LIST_ITEM);
    }

    /**
     * {@inheritDoc}.
     */
    @Override
    public final boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
	    case R.id.privacy_list_menu_create:
		showDialog(DIALOG_CREATE_PRIVACY_LIST);
		return true;
	    default:
		return false;
	}
    }

    private final class BeemServiceConnection implements ServiceConnection {

	private IXmppFacade mXmppFacade;

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
	    Log.v(TAG, "BEGIN onServiceConnected.");
	    mXmppFacade = IXmppFacade.Stub.asInterface(service);
	    mBroadcastReceiver.setBinded(true);
	    try {
		mPrivacyListManager = mXmppFacade.getPrivacyListManager();
		mPrivacyListManager.addPrivacyListListener(mPrivacyListListener);
		mPrivacyListNames.clear();
		mPrivacyListNames.addAll(mPrivacyListManager.getPrivacyLists());
		mAdapter.notifyDataSetChanged();
	    } catch (RemoteException e) {
		Log.e(TAG, e.getMessage());
	    }
	    Log.v(TAG, "END onServiceConnected.");
	}

	@Override
	public void onServiceDisconnected(ComponentName name) {
	    Log.v(TAG, "BEGIN onServiceDisconnected.");
	    mXmppFacade = null;
	    mBroadcastReceiver.setBinded(false);
	    try {
		mPrivacyListManager.removePrivacyListListener(mPrivacyListListener);
	    } catch (RemoteException e) {
		Log.e(TAG, e.getMessage());
	    }
	    Log.v(TAG, "END onServiceDisconnected.");
	}
    }

    private class PrivacyListListener extends IPrivacyListListener.Stub {

	@Override
	public void setPrivacyList(String listName, List<PrivacyListItem> listItem) throws RemoteException {
	    Log.d(TAG, "BEGIN PrivacyListListener >> setPrivacyList.");
	    Log.d(TAG, "> " + listName + " has been setted.");
	    Log.d(TAG, "END PrivacyListListener >> setPrivacyList.");
	}

	@Override
	public void updatedPrivacyList(final String listName) throws RemoteException {
	    Log.d(TAG, "BEGIN PrivacyListListener >> updatedPrivacyList.");
	    mHandler.post(new Runnable() {
		@Override
		public void run() {
		    try {
			mPrivacyListNames.clear();
			// Not that much lists and require some server queries to know if the list has been
			// updated/deleted or set to default/active by this activity or another IM client.
			mPrivacyListNames.addAll(mPrivacyListManager.getPrivacyLists());
		    } catch (RemoteException e) {
			Log.e(TAG, e.getMessage());
		    }
		    mAdapter.notifyDataSetChanged();
		}
	    });
	    Log.d(TAG, "END PrivacyListListener >> updatedPrivacyList.");
	}
    }
}
