package com.cyrilmottier.android.queryhighlight;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;
import com.cyrilmottier.android.queryhighlight.text.Normalizer;
import com.cyrilmottier.android.queryhighlight.text.TextWatcherAdapter;
import com.cyrilmottier.android.queryhighlight.text.format.QueryHighlighter;

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

public final class MainActivity extends AppCompatActivity {

    private CheesesAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mAdapter = new CheesesAdapter();

        final ListView listView = (ListView) findViewById(android.R.id.list);
        listView.setAdapter(mAdapter);

        final ActionBar actionBar = getSupportActionBar();
        actionBar.setCustomView(R.layout.search_view);
        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);

        final EditText editText = (EditText) actionBar.getCustomView();
        editText.addTextChangedListener(mTextWatcher);
        editText.requestFocus();
    }

    public final class CheesesAdapter extends BaseAdapter implements Filterable {

        private final QueryHighlighter mQueryHighlighter;
        private final Filter mFilter;

        private List<String> mCheeses;
        private String mQuery;

        public CheesesAdapter() {
            mCheeses = Cheeses.ALL;
            mFilter = new WordFilter(mCheeses);
            mQueryHighlighter = new QueryHighlighter().
                    setQueryNormalizer(QueryHighlighter.QueryNormalizer.FOR_SEARCH);
        }

        @Override
        public int getCount() {
            return mCheeses.size();
        }

        @Override
        public String getItem(int position) {
            return mCheeses.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean isEnabled(int position) {
            return false;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.list_item_text, parent, false);
            }

            mQueryHighlighter.setText((TextView) convertView, getItem(position), mQuery);

            return convertView;
        }

        // NOTE Cyril
        //   - ArrayAdapter has built-in filtering by default but normalization
        //     is only case-based.
        //   - CursorAdapter has built-int filtering too. However, try to favor
        //     restarting a query (with a Loader for instance) instead.
        //   - When data comes from the network, it's up to you to restart the
        //     query.
        @Override
        public Filter getFilter() {
            return mFilter;
        }

        public void setQuery(String query) {
            if (!Objects.equals(query, mQuery)) {
                getFilter().filter(query);
            }
        }

        private final class WordFilter extends Filter {

            private final List<String> mItems;

            private WordFilter(List<String> items) {
                mItems = new ArrayList<>(items);
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                final List<String> list;

                if (TextUtils.isEmpty(constraint)) {
                    list = mItems;
                } else {
                    list = new ArrayList<>();
                    final String normalizedConstraint = Normalizer.forSearch(constraint);
                    for (String item : mItems) {
                        final String normalizedItem = Normalizer.forSearch(item);
                        if (normalizedItem.startsWith(normalizedConstraint) || //
                                normalizedItem.contains(" " + normalizedConstraint)) {
                            list.add(item);
                        }
                    }
                }

                final FilterResults results = new FilterResults();
                results.values = list;
                results.count = list.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                //noinspection unchecked
                mCheeses = (List<String>) results.values;
                mQuery = constraint != null ? constraint.toString() : null;
                mAdapter.notifyDataSetChanged();
            }
        }
    }

    private final TextWatcher mTextWatcher = new TextWatcherAdapter() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            mAdapter.setQuery(s != null ? s.toString() : null);
        }
    };

}