/*
    BEEM is a videoconference application on the Android Platform.

    Copyright (C) 2009 by Frederic-Charles Barthelery,
                          Jean-Manuel Da Silva,
                          Nikita Kozlov,
                          Philippe Lago,
                          Jean Baptiste Vergely,
                          Vincent Veronis.

    This file is part of BEEM.

    BEEM is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BEEM is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.

    Please send bug reports with examples or suggestions to
    contact@beem-project.com or http://dev.beem-project.com/
 */
package com.beem.project.beem.ui;

import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.Gallery;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

import com.beem.project.beem.BeemApplication;
import com.beem.project.beem.BeemIntent;
import com.beem.project.beem.R;
import com.beem.project.beem.ui.wizard.AccountConfigure;

/**
 * The contact list activity displays the roster of the user.
 * @author Vincent V. <marseille@beem-project.com>
 */
public class ContactList extends Activity {

    private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
    private static final String TAG = "ContactList";

    /**
     * Map containing a list of the different contacts of a given group. Each list is a @{link SortedList} so there is
     * no need to sort it again.
     */

    private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();

    private SharedPreferences mSettings;
    private BeemBanner mAdapterBanner;
    private BeemContactList mAdapterContactList;

    private String mAccountName;

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

    @Override
    protected void onCreate(Bundle saveBundle) {
	super.onCreate(saveBundle);

	setContentView(R.layout.contactlist);
	Bundle b = getIntent().getExtras();
	if (b == null) {
	    //TODO: Add toast to advice need to configure at least 1 beem account (Should not happend)
	    startActivity(new Intent(ContactList.this, AccountConfigure.class));
	}
	mAccountName = b.getString(BeemIntent.EXTRA_ACCOUNT);
	if (mAccountName == null) {
	    //TODO: Add toast to advice need to configure at least 1 beem account (Should not happend)
	    startActivity(new Intent(ContactList.this, AccountConfigure.class));
	}
	mSettings = getSharedPreferences(mAccountName, MODE_PRIVATE);

	// Get Groups list
	final Cursor cursorGroup = getContentResolver().query(ContactsContract.Groups.CONTENT_URI,
	    new String[] { ContactsContract.Groups._ID, ContactsContract.Groups.TITLE },
	    ContactsContract.Groups.ACCOUNT_NAME + "=?", new String[] { mAccountName }, null);
	mAdapterBanner = new BeemBanner(this, R.layout.contactlist_group, cursorGroup,
	    new String[] { ContactsContract.Groups.TITLE }, new int[] { R.id.contactlist_group });
	cursorGroup.registerContentObserver(new BeemGroupObserver(new Handler()));

	// Get Contacts list
	final Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon()
	    .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, mAccountName)
	    .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, BeemApplication.BEEM_PACKAGE).build();
	Cursor cursorRawContact = getContentResolver().query(rawContactUri, null,
	    ContactsContract.RawContacts.DELETED + "= 0", null, null);

	mAdapterContactList = new BeemContactList(this, R.layout.contactlistcontact, cursorRawContact, new String[] {
	    ContactsContract.RawContacts._ID, ContactsContract.RawContacts.CONTACT_ID,
	    ContactsContract.RawContacts.SOURCE_ID }, new int[] { R.id.avatar, R.id.contactlistpseudo,
	    R.id.contactlistmsgperso });

	ListView listView = (ListView) findViewById(R.id.contactlist);
	listView.setOnItemClickListener(mOnContactClick);
	registerForContextMenu(listView);
	listView.setAdapter(mAdapterContactList);

	//	mAdapterContactList.setFilterQueryProvider(new FilterQueryProvider() {
	//	    public Cursor runQuery(CharSequence constraint) {
	//		String s = '%' + constraint.toString() + '%';
	//		return getContentResolver().query(rawContactUri, null,
	//		    ContactsContract.RawContacts.SOURCE_ID+ " LIKE ? ", new String[] { s }, null);
	//	    }
	//	});
    }

    @Override
    protected void onResume() {
	super.onResume();
	Log.e(TAG, "onResume : " + mSettings.getBoolean("settings_key_hide_groups", false));
	if (!mSettings.getBoolean("settings_key_hide_groups", false))
	    showGroups();
	else
	    hideGroups();
    }

    @Override
    public final boolean onCreateOptionsMenu(Menu menu) {
	super.onCreateOptionsMenu(menu);
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.contact_list, menu);
	return true;
    }

    @Override
    public final boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
	    case R.id.contact_list_menu_settings:
		Intent i = new Intent(this, Settings.class);
		i.putExtra("account_name", mAccountName);
		startActivity(i);
		return true;
	    case R.id.contact_list_menu_add_contact:
		startActivity(new Intent(ContactList.this, AddContact.class));
		return true;
	    case R.id.menu_change_status:
		startActivity(new Intent(ContactList.this, ChangeStatus.class));
		return true;
	    case R.id.contact_list_menu_chatlist:
		//		List<Contact> openedChats;
		//		try {
		//		    openedChats = mChatManager.getOpenedChatList();
		//		    Log.d(TAG, "opened chats = " + openedChats);
		//		    Dialog chatList = new ChatList(ContactList.this, openedChats).create();
		//		    chatList.show();
		//		} catch (RemoteException e) {
		//		    e.printStackTrace();
		//		}
		//		return true;
	    case R.id.contact_list_menu_sync:
		Intent intent = new Intent(BeemIntent.ACTION_SYNC);
		intent.putExtra(BeemIntent.EXTRA_ACCOUNT, mAccountName);
		startService(intent);
		return true;
	    case R.id.menu_disconnect:
		return true;
	    default:
		return false;
	}
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
	super.onCreateContextMenu(menu, v, menuInfo);
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.contactlist_context, menu);
	AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
	// Contact c = new Contact();
	// try {
	// mSelectedContact = mRoster.getContact(c.getJID());
	// } catch (RemoteException e) {
	// e.printStackTrace();
	// }
	// menu.setHeaderTitle(mSelectedContact.getJID());
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
	Intent in;
	boolean result;
	switch (item.getItemId()) {
	    case R.id.contact_list_context_menu_chat_item:
		//		    List<String> res = mSelectedContact.getMRes();
		//		    if (res.isEmpty()) {
		//			result = false;
		//			break;
		//		    }
		//		    for (String resv : res) {
		//			in = new Intent(this, Chat.class);
		//			in.setData(mSelectedContact.toUri(resv));
		//			item.getSubMenu().add(resv).setIntent(in);
		//		    }
		result = true;
		break;
	    case R.id.contact_list_context_menu_call_item:
		//		    try {
		//			mXmppFacade.call(mSelectedContact.getJID() + "/psi");
		//			result = true;
		//		    } catch (RemoteException e) {
		//			e.printStackTrace();
		//		    }
		result = true;
		break;
	    case R.id.contact_list_context_menu_user_info:
		//		    item.getSubMenu().setHeaderTitle(mSelectedContact.getJID());
		result = true;
		break;
	    case R.id.contact_list_context_menu_userinfo_alias:
		//		    Dialog alias = new Alias(ContactList.this, mRoster, mSelectedContact).create();
		//		    alias.show();
		result = true;
		break;
	    case R.id.contact_list_context_menu_userinfo_group:
		//		    in = new Intent(this, GroupList.class);
		//		    in.putExtra("contact", mSelectedContact);
		//		    startActivity(in);
		result = true;
		break;
	    case R.id.contact_list_context_menu_userinfo_subscription:
		//		    Dialog subscription = new ResendSubscription(ContactList.this, mXmppFacade, mSelectedContact)
		//			.create();
		//		    subscription.show();
		result = true;
		break;
	    case R.id.contact_list_context_menu_userinfo_block:
		result = true;
		break;
	    case R.id.contact_list_context_menu_userinfo_delete:
		//		    Dialog delete = new DeleteContact(ContactList.this, mRoster, mSelectedContact).create();
		//		    delete.show();
		result = true;
		break;
	    default:
		result = super.onContextItemSelected(item);
		break;
	}
	return result;
    }

    /**
     * Show the groups view.
     */
    private void showGroups() {
	Log.e(TAG, "SHOWGROUPS");
	ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub);
	if (stub != null) {
	    View v = stub.inflate();
	    Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
	    g.setOnItemClickListener(new OnItemClickGroupName());
	    g.setAdapter(mAdapterBanner);
	    Log.e(TAG, "SHOWGROUPS" + mAdapterBanner.getCount());
	    if (mAdapterBanner.getCount() == 0)
		v.setVisibility(View.GONE);
	    else
		v.setVisibility(View.VISIBLE);
	}
    }

    /**
     * Hide the groups view.
     */
    private void hideGroups() {
	Log.e(TAG, "hideGroups");
	View v = findViewById(R.id.contactlist_groupstub);
	if (v != null)
	    v.setVisibility(View.GONE);
    }

    /**
     * Adapter contact list.
     */
    private static class BeemContactList extends SimpleCursorAdapter implements Filterable {

	private Context mContext;
	private int mLayout;
	private final ContactFilter mContactFilter = new ContactFilter();
	private final GroupFilter mGroupFilter = new GroupFilter();

	public BeemContactList(Context context, int layout, Cursor c, String[] from, int[] to) {
	    super(context, layout, c, from, to);
	    mContext = context;
	    mLayout = layout;
	}

	@Override
	public View newView(Context context, Cursor cursor, ViewGroup parent) {
	    final LayoutInflater inflater = LayoutInflater.from(mContext);
	    return inflater.inflate(mLayout, parent, false);
	}

	@Override
	public void bindView(View view, Context context, Cursor cursor) {
	    long id = cursor.getLong(cursor.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID));

	    Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, id);
	    Uri entityUri = Uri.withAppendedPath(rawContactUri, ContactsContract.RawContacts.Entity.CONTENT_DIRECTORY);
	    Cursor cursorContact = mContext.getContentResolver().query(
		entityUri,
		new String[] { ContactsContract.RawContacts.SOURCE_ID, ContactsContract.RawContacts.Entity.DATA_ID,
		    ContactsContract.RawContacts.Entity.MIMETYPE, ContactsContract.RawContacts.Entity.DATA1 }, null,
		null, null);
	    Log.e(TAG, "BINDVIEW");
	    try {
		while (cursorContact.moveToNext()) {
		    if (!cursorContact.isNull(1)) {
			String mimeType = cursorContact.getString(2);
			String data = cursorContact.getString(3);
			if (mimeType.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) {
			    TextView nameText = (TextView) view.findViewById(R.id.contactlistpseudo);
			    nameText.setText(data);
			}
			//else if other mimetype

		    }

		}
	    } finally {
		cursorContact.close();
	    }

	    String jid = cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.SOURCE_ID));
	    view.setTag(jid);

	    // ImageView img = (ImageView) view.findViewById(R.id.avatar);
	    // String avatarId = curContact.getAvatarId();
	    // int contactStatus = curContact.getStatus();
	    // Drawable avatar = getAvatarStatusDrawable(avatarId);
	    // img.setImageDrawable(avatar);
	    // img.setImageLevel(contactStatus);
	}

	public Filter getContactFilter() {
	    return mContactFilter;
	}

	public Filter getGroupFilter() {
	    return mGroupFilter;
	}

	/**
	 * Get a LayerDrawable containing the avatar and the status icon. The status icon will change with the level of
	 * the drawable.
	 * @param avatarId the avatar id to retrieve or null to get default
	 * @return a LayerDrawable
	 */
	// private Drawable getAvatarStatusDrawable(String avatarId) {
	// Drawable avatarDrawable = null;
	// if (avatarId != null) {
	// Uri uri =
	// AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build();
	// InputStream in = null;
	// try {
	// try {
	// in = getContentResolver().openInputStream(uri);
	// avatarDrawable = Drawable.createFromStream(in, avatarId);
	// } finally {
	// if (in != null)
	// in.close();
	// }
	// } catch (IOException e) {
	// Log.w(TAG, "Error while setting the avatar", e);
	// }
	// }
	// if (avatarDrawable == null)
	// avatarDrawable =
	// getResources().getDrawable(R.drawable.beem_launcher_icon_silver);
	// LayerDrawable ld = (LayerDrawable)
	// getResources().getDrawable(R.drawable.avatar_status);
	// ld.setLayerInset(1, 36, 36, 0, 0);
	// ld.setDrawableByLayerId(R.id.avatar, avatarDrawable);
	// return ld;
	// }

	/**
	 * A Filter which select Contact to display by searching in ther Jid.
	 */
	private class ContactFilter extends Filter {

	    /**
	     * Create a ContactFilter.
	     */
	    public ContactFilter() {
	    }

	    @Override
	    protected Filter.FilterResults performFiltering(CharSequence constraint) {
		Log.d(TAG, "performFiltering");
		//		while (mCursor.moveToNext()) {
		//		    
		//		}
		//		List<Contact> result = mListContact;
		//		if (constraint.length() > 0) {
		//		    result = new LinkedList<Contact>();
		//		    for (Contact c : mContactOnGroup.get(mSelectedGroup)) {
		//			if (c.getJID().contains(constraint))
		//			    result.add(c);
		//		    }
		//		}
		//		Filter.FilterResults fr = new Filter.FilterResults();
		//		fr.values = result;
		//		fr.count = result.size();
		//		return fr;
		return null;
	    }

	    @Override
	    protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
		Log.d(TAG, "publishResults");
		//		List<Contact> contacts = (List<Contact>) results.values;
		//		mListContact = contacts;
		//		notifyDataSetChanged();
	    }
	}

	/**
	 * A Filter which select Contact to display by searching in ther Jid.
	 */
	private class GroupFilter extends Filter {

	    /**
	     * Create a ContactFilter.
	     */
	    public GroupFilter() {
	    }

	    @Override
	    protected Filter.FilterResults performFiltering(CharSequence constraint) {
		Log.d(TAG, "performFiltering");

		Cursor cursorContact = mContext.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
		    new String[] { ContactsContract.Data.RAW_CONTACT_ID }, ContactsContract.Data.MIMETYPE + " =? ",
		    new String[] { ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE }, null);
		try {
		    while (cursorContact.moveToNext()) {
			Log.e(
			    TAG,
			    "HOW MUCH "
				+ cursorContact.getString(cursorContact
				    .getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID)));
		    }
		} finally {
		    cursorContact.close();
		}

		Filter.FilterResults fr = new Filter.FilterResults();
		fr.values = cursorContact;
		fr.count = cursorContact.getCount();
		return fr;
	    }

	    @Override
	    protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
		Log.d(TAG, "publishResults " + results.count);
	    }
	}
    }

    /**
     * Adapter banner group list.
     */
    private static class BeemBanner extends SimpleCursorAdapter {

	private Context mContext;
	private int mLayout;

	public BeemBanner(Context context, int layout, Cursor c, String[] from, int[] to) {
	    super(context, layout, c, from, to);
	    mContext = context;
	    mLayout = layout;
	}

	@Override
	public View newView(Context context, Cursor cursor, ViewGroup parent) {
	    final LayoutInflater inflater = LayoutInflater.from(mContext);
	    return inflater.inflate(mLayout, parent, false);
	}

	@Override
	public void bindView(View view, Context context, Cursor cursor) {
	    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Groups.TITLE));
	    TextView nameText = (TextView) view.findViewById(R.id.contactlist_group);
	    if (nameText != null) {
		nameText.setText(name);
	    }
	}
    }

    /**
     * Event simple click on item of the contact list.
     */
    private class BeemContactListOnClick implements OnItemClickListener {
	/**
	 * Constructor.
	 */
	public BeemContactListOnClick() {
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
	    String jid = (String) v.getTag();
	    Log.i(TAG, "OnClick Jid :" + jid);
	    Intent i = new Intent(ContactList.this, Chat.class);
	    i.setData(Uri.parse("imto://jabber/" + jid));
	    startActivity(i);
	}
    }

    /**
     * Event simple click on middle group name.
     */
    private class OnItemClickGroupName implements OnItemClickListener {

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

	@Override
	public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
	    Log.e(TAG, "ONGROUPCLICK");
	    TextView nameGroup = (TextView) v.findViewById(R.id.contactlist_group);
	    Uri groupUri = ContactsContract.Groups.CONTENT_URI.buildUpon()
		.appendQueryParameter(ContactsContract.Groups.ACCOUNT_NAME, mAccountName)
		.appendQueryParameter(ContactsContract.Groups.ACCOUNT_TYPE, BeemApplication.BEEM_PACKAGE)
		.appendQueryParameter(ContactsContract.Groups.TITLE, nameGroup.toString()).build();
	    nameGroup.setTextColor(R.color.vert_manu);
	    Cursor cursorGroup = getContentResolver().query(groupUri, null, ContactsContract.Groups.DELETED + "= 0",
		null, null);
	    if (cursorGroup.moveToFirst()) {
		String _id = cursorGroup.getString(cursorGroup.getColumnIndex(ContactsContract.Groups._ID));
		mAdapterContactList.getGroupFilter().filter(_id);
	    }
	}
    }

    /**
     * Class to observe modification in groups.
     */
    private class BeemGroupObserver extends ContentObserver {

	public BeemGroupObserver(Handler handler) {
	    super(handler);
	}

	@Override
	public boolean deliverSelfNotifications() {
	    return true;
	}

	@Override
	public void onChange(boolean selfChange) {
	    super.onChange(selfChange);
	    View v = findViewById(R.id.contactlist_groupstub);
	    if (v != null) {
		if (mAdapterBanner.getCount() > 0) {
		    v.setVisibility(View.VISIBLE);
		} else {
		    v.setVisibility(View.GONE);
		}
	    }
	}

    }

}
