package cgeo.contacts;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.Pair;
import android.view.Gravity;
import android.widget.Toast;

import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

public final class ContactsActivity extends Activity {
    static final String LOG_TAG = "cgeo.contacts";

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Uri uri = getIntent().getData();
        if (uri == null) {
            finish();
            return;
        }

        final String nickName = getParameter(uri, IContacts.PARAM_NAME);
        if (StringUtils.isEmpty(nickName)) {
            finish();
            return;
        }

        // search by nickname, exact
        List<Pair<Integer, String>> contacts = getContacts(nickName, ContactsContract.Data.CONTENT_URI, ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Nickname.NAME, false);

        // search by display name, exact
        if (contacts.isEmpty()) {
            contacts = getContacts(nickName, ContactsContract.Contacts.CONTENT_URI, BaseColumns._ID, ContactsContract.Contacts.DISPLAY_NAME, false);
        }

        // search by contained name parts
        if (contacts.isEmpty()) {
            contacts.addAll(getContacts(nickName, ContactsContract.Data.CONTENT_URI, ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Nickname.NAME, true));
            contacts.addAll(getContacts(nickName, ContactsContract.Contacts.CONTENT_URI, BaseColumns._ID, ContactsContract.Contacts.DISPLAY_NAME, true));
        }

        if (contacts.isEmpty()) {
            showToast(getString(R.string.contact_not_found, nickName));
            finish();
            return;
        }

        if (contacts.size() > 1) {
            selectContact(contacts);
        } else {
            final int contactId = contacts.get(0).first;
            openContactAndFinish(contactId);
        }
    }

    private void selectContact(@NonNull final List<Pair<Integer, String>> contacts) {
        final List<String> list = new ArrayList<>();
        for (final Pair<Integer, String> p : contacts) {
            list.add(p.second);
        }
        final CharSequence[] items = list.toArray(new CharSequence[list.size()]);
        new AlertDialog.Builder(this)
                .setTitle(R.string.multiple_matches)
                .setItems(items, new OnClickListener() {

                    @Override
                    public void onClick(final DialogInterface dialog, final int which) {
                        final int contactId = contacts.get(which).first;
                        dialog.dismiss();
                        openContactAndFinish(contactId);
                    }
                })
                .setOnCancelListener(new OnCancelListener() {

                    @Override
                    public void onCancel(final DialogInterface dialog) {
                        dialog.dismiss();
                        finish();
                    }
                })
                .create().show();
    }

    private void openContactAndFinish(final int id) {
        final Intent intent = new Intent(Intent.ACTION_VIEW);
        final Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(id));
        intent.setData(uri);
        startActivity(intent);
        finish();
    }

    @NonNull
    private List<Pair<Integer, String>> getContacts(@NonNull final String searchName, final Uri uri, @NonNull final String idColumnName, @NonNull final String selectionColumnName, final boolean like) {
        final String[] projection = { idColumnName, selectionColumnName, ContactsContract.Contacts.DISPLAY_NAME };
        final String selection = selectionColumnName + (like ? " LIKE" : " =") + " ? COLLATE NOCASE";
        final String[] selectionArgs = { like ? "%" + searchName + "%" : searchName };
        Cursor cursor = null;

        final List<Pair<Integer, String>> result = new ArrayList<>();
        try {
            cursor = getContentResolver().query(uri, projection, selection, selectionArgs, null);
            while (cursor != null && cursor.moveToNext()) {
                final int foundId = cursor.getInt(0);
                final String foundName = cursor.getString(1);
                final String displayName = cursor.getString(2);
                result.add(new Pair<>(foundId, StringUtils.isNotEmpty(displayName) &&
                        !StringUtils.equalsIgnoreCase(foundName, displayName) ? foundName + " (" + displayName + ")" : foundName));
            }
        } catch (final Exception e) {
            Log.e(LOG_TAG, "ContactsActivity.getContactId", e);
        } finally {
            if (cursor != null) {
                cursor.close(); // no Closable Cursor below sdk 16
            }
        }
        return result;
    }

    public void showToast(final String text) {
        final Toast toast = Toast.makeText(this, text, Toast.LENGTH_LONG);

        toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 100);
        toast.show();
    }

    @NonNull
    private static String getParameter(@NonNull final Uri uri, @NonNull final String paramKey) {
        try {
            final String param = uri.getQueryParameter(paramKey);
            if (param == null) {
                return StringUtils.EMPTY;
            }
            return URLDecoder.decode(param, CharEncoding.UTF_8).trim();
        } catch (final UnsupportedEncodingException e) {
            Log.e(LOG_TAG, "ContactsActivity.getParameter", e);
        }
        return StringUtils.EMPTY;
    }

}

@@ -580,100 +580,8 @@
 t;%0A%0A
-import org.apache.commons.lang3.CharEncoding;%0Aimport org.apache.commons.lang3.StringUtils;%0A%0A
 impo
@@ -701,16 +701,109 @@
 .List;%0A%0A
+import org.apache.commons.lang3.CharEncoding;%0Aimport org.apache.commons.lang3.StringUtils;%0A%0A%0A
 public f

Fix import order in ContactsActivity