package com.example.android.actionmode_listview_dynamic_layout;

import android.app.ListActivity;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.routine_work.widget.CheckableLinearLayout;

public class UserListActivity extends ListActivity
{

	private static final String LOG_TAG = "XXX";
	private static final String MAPPING_KEY_NAME = "name";
	private static final String MAPPING_KEY_EMAIL = "email";
	private static final String[] MAPPING_FROM = new String[]
	{
		MAPPING_KEY_NAME,
		MAPPING_KEY_EMAIL,
	};
	private static final int[] MAPPING_TO = new int[]
	{
		R.id.user_name_textview,
		R.id.user_email_textview,
	};
	private List<Map<String, String>> userListData = new ArrayList<Map<String, String>>();
	private SimpleAdapter userListAdapter;
	private UserViewBinder userViewBinder;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		Log.v(LOG_TAG, "onCreate() : Hello");

		super.onCreate(savedInstanceState);
		setContentView(R.layout.user_list_activity);

		userViewBinder = new UserViewBinder();

		// init nameListData
		Resources resources = getResources();
		String[] names = resources.getStringArray(R.array.names);
		for (String name : names)
		{
			String email = name.toLowerCase() + "@example.com";
			Map<String, String> userData = new HashMap<String, String>();
			userData.put(MAPPING_KEY_NAME, name);
			userData.put(MAPPING_KEY_EMAIL, email);
			userListData.add(userData);
		}

		// init userListAdapter
		userListAdapter = new SimpleAdapter(this,
			userListData, R.layout.user_list_item,
			MAPPING_FROM, MAPPING_TO);
		userListAdapter.setViewBinder(userViewBinder);
		setListAdapter(userListAdapter);

		// init ListView
		ListView listView = getListView();
		listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
		listView.setMultiChoiceModeListener(new MultiChoideDeleteModeListener());

		Log.v(LOG_TAG, "onCreate() : Bye");
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.user_list_activity_option_menu, menu);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		boolean result = true;
		Log.v(LOG_TAG, "onOptionsItemSelected() : Hello");

		switch (item.getItemId())
		{
			case R.id.quit_menuitem:
				finish();
				break;
			default:
				result = super.onOptionsItemSelected(item);
		}

		Log.v(LOG_TAG, "onOptionsItemSelected() : Bye");
		return result;
	}

	private void deleteCheckedItems()
	{
		Log.v(LOG_TAG, "deleteCheckedItems() : Hello");

		long[] checkItemIds = getListView().getCheckItemIds();
		Log.d(LOG_TAG, "deleteCheckedItems() : checkItemIds => " + checkItemIds);
		if (checkItemIds != null && checkItemIds.length > 0)
		{
			Log.d(LOG_TAG, "deleteCheckedItems() : checkItemIds.length => " + checkItemIds.length);
			for (int i = checkItemIds.length - 1; i >= 0; i--)
			{
				Log.d(LOG_TAG, "deleteCheckedItems() : delete at => " + checkItemIds[i]);
				userListData.remove((int) checkItemIds[i]);
			}
			userListAdapter.notifyDataSetChanged();
		}

		Log.v(LOG_TAG, "deleteCheckedItems() : Bye");
	}

	class MultiChoideDeleteModeListener implements AbsListView.MultiChoiceModeListener
	{

		public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean checked)
		{
			Log.v(LOG_TAG, "onItemCheckedStateChanged() : Hello");
			Log.v(LOG_TAG, "onItemCheckedStateChanged() : Bye");
		}

		public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
		{
			Log.v(LOG_TAG, "onCreateActionMode() : Hello");

			MenuInflater menuInflater = getMenuInflater();
			menuInflater.inflate(R.menu.user_list_delete_mode_option_menu, menu);

			actionMode.setTitle(R.string.delete_users);

			Log.v(LOG_TAG, "onCreateActionMode() : Bye");
			return true;
		}

		public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
		{
			Log.v(LOG_TAG, "onPrepareActionMode() : Hello");

			userViewBinder.setCheckboxVisible(true);

			Log.v(LOG_TAG, "onPrepareActionMode() : Bye");
			return true;
		}

		public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
		{
			boolean result = true;
			Log.v(LOG_TAG, "onPrepareActionMode() : Hello");

			switch (menuItem.getItemId())
			{
				case R.id.delete_menuitem:
					deleteCheckedItems();
					actionMode.finish();
					break;
				default:
					result = false;
			}

			Log.v(LOG_TAG, "onPrepareActionMode() : Bye");
			return result;
		}

		public void onDestroyActionMode(ActionMode actionMode)
		{
			Log.v(LOG_TAG, "onDestroyActionMode() : Hello");

			userViewBinder.setCheckboxVisible(false);

			Log.v(LOG_TAG, "onDestroyActionMode() : Bye");
		}
	};

	private static class UserViewBinder implements ViewBinder
	{

		private boolean checkboxVisible = false;

		public boolean isCheckboxVisible()
		{
			return checkboxVisible;
		}

		public void setCheckboxVisible(boolean checkboxVisible)
		{
			this.checkboxVisible = checkboxVisible;
		}

		public UserViewBinder()
		{
		}

		/**
		 * CheckedTextView の表示・非表示を設定するだけで実際の値の設定は SimpleAdapter に任せる。
		 *
		 * @param view
		 * @param value
		 * @param valueText
		 * @return
		 */
		public boolean setViewValue(View view, Object value, String valueText)
		{
			Log.d(LOG_TAG, "view => " + view);
			CheckableLinearLayout listItemView = findCheckableLinearLayout(view);
			Log.d(LOG_TAG, "listItemView => " + listItemView);
			View foundView = listItemView.findViewById(android.R.id.checkbox);
			if (foundView instanceof CheckedTextView)
			{
				CheckedTextView checkedTextView = (CheckedTextView) foundView;
				Log.d(LOG_TAG, "checkedTextView => " + checkedTextView);
				Log.d(LOG_TAG, "isCheckboxVisible() => " + isCheckboxVisible());
				if (isCheckboxVisible())
				{
					checkedTextView.setVisibility(View.VISIBLE);
				}
				else
				{
					checkedTextView.setVisibility(View.GONE);
				}
				Log.d(LOG_TAG, "checkedTextView.visibility => " + checkedTextView.getVisibility());
			}

			return false;
		}

		private static CheckableLinearLayout findCheckableLinearLayout(View view)
		{
			CheckableLinearLayout result = null;
			View target = view;

			while ((target != null) && ((target instanceof CheckableLinearLayout) == false))
			{
				target = (View) target.getParent();
			}

			if (target != null)
			{
				result = (CheckableLinearLayout) target;
			}

			return result;
		}
	}
}
