package org.zeroxlab.momodict.ui;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import org.zeroxlab.momodict.Controller;
import org.zeroxlab.momodict.Momodict;
import org.zeroxlab.momodict.R;
import org.zeroxlab.momodict.WordActivity;
import org.zeroxlab.momodict.widget.BackKeyHandler;
import org.zeroxlab.momodict.widget.DictionaryRowPresenter;
import org.zeroxlab.momodict.widget.SelectorAdapter;
import org.zeroxlab.momodict.widget.WordRowPresenter;

import java.util.HashMap;
import java.util.Map;

import rx.android.schedulers.AndroidSchedulers;

public class InputFragment extends Fragment implements BackKeyHandler {

    private static final String TAG = Momodict.TAG;

    private SelectorAdapter mAdapter;
    private EditText mInput;
    private Controller mCtrl;

    @Override
    public void onCreate(@Nullable Bundle savedState) {
        super.onCreate(savedState);

        mCtrl = new Controller(getActivity());
        final Map<SelectorAdapter.Type, SelectorAdapter.Presenter> map = new HashMap<>();
        map.put(SelectorAdapter.Type.A, new DictionaryRowPresenter());
        map.put(SelectorAdapter.Type.B,
                new WordRowPresenter((view) -> onRowClicked((String) view.getTag())));
        mAdapter = new SelectorAdapter(map);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
        final View fragmentView = inflater.inflate(R.layout.fragment_input, container, false);
        initViews(fragmentView);
        return fragmentView;
    }

    @Override
    public void onResume() {
        super.onResume();
        onUpdateInput();
        onUpdateList();
    }

    @Override
    public boolean backKeyHandled() {
        if (TextUtils.isEmpty(mInput.getText())) {
            return false;
        } else {
            clearInput();
            return true;
        }
    }

    private void initViews(@NonNull View fv) {
        final RecyclerView list = (RecyclerView) fv.findViewById(R.id.list);
        final LinearLayoutManager mgr = (LinearLayoutManager) list.getLayoutManager();
        final DividerItemDecoration decoration = new DividerItemDecoration(list.getContext(),
                mgr.getOrientation());
        list.addItemDecoration(decoration);
        mInput = (EditText) fv.findViewById(R.id.input_1);
        mInput.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                onUpdateList();
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });

        list.setAdapter(mAdapter);
        fv.findViewById(R.id.btn_1).setOnClickListener((v) -> clearInput());
    }

    private void clearInput() {
        mInput.setText("");
    }

    private void onUpdateInput() {
        mCtrl.getBooks()
                .count()
                .subscribe((count) -> {
                    mInput.setEnabled(count > 0);
                    if (count > 0 && !TextUtils.isEmpty(mInput.getText())) {
                        mInput.selectAll();
                    }
                });
    }

    private void onUpdateList() {
        final String input = mInput.getText().toString();
        Log.d(TAG, "Input: " + input);
        mAdapter.clear();
        if (TextUtils.isEmpty(input)) {
            mCtrl.getBooks()
                    .subscribe(
                            (book) -> mAdapter.addItem(book.bookName, SelectorAdapter.Type.A),
                            (e) -> e.printStackTrace(),
                            () -> mAdapter.notifyDataSetChanged());

        } else {
            mCtrl.queryEntries(input)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(
                            (entry) -> mAdapter.addItem(entry.wordStr, SelectorAdapter.Type.B),
                            (e) -> e.printStackTrace(),
                            () -> mAdapter.notifyDataSetChanged());
        }
    }

    private void onRowClicked(String text) {
        final Intent intent = WordActivity.createIntent(getActivity(), text);
        startActivity(intent);
    }
}

@@ -769,16 +769,58 @@
 tivity;%0A
+import org.zeroxlab.momodict.model.Entry;%0A
 import o
@@ -859,24 +859,24 @@
 KeyHandler;%0A
-
 import org.z
@@ -1078,16 +1078,54 @@
 til.Map;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aimport
@@ -1165,16 +1165,79 @@
 edulers;
+%0Aimport rx.subjects.PublishSubject;%0Aimport rx.subjects.Subject;
 %0A%0Apublic
@@ -1354,16 +1354,64 @@
 ict.TAG;
+%0A    private static final int INPUT_DELAY = 500;
 %0A%0A    pr
@@ -1502,16 +1502,87 @@
 mCtrl;%0A%0A
+    private Subject%3CString, String%3E mQuery = PublishSubject.create();%0A%0A
     @Ove
@@ -2011,24 +2011,24 @@
 etTag())));%0A
-
         mAda
@@ -2059,16 +2059,681 @@
 er(map);
+%0A%0A        // If user type quickly, do not query until user stop inputting.%0A        mQuery.debounce(INPUT_DELAY, TimeUnit.MILLISECONDS)%0A                .concatMap((input) -%3E mCtrl.queryEntries(input).toList())%0A                .observeOn(AndroidSchedulers.mainThread())%0A                .subscribe((list) -%3E %7B%0A                    for (Entry entry : list) %7B%0A                        mAdapter.addItem(entry.wordStr, SelectorAdapter.Type.B);%0A                    %7D%0A                    mAdapter.notifyDataSetChanged();%0A                %7D, (e) -%3E e.printStackTrace());%0A    %7D%0A%0A    @Override%0A    public void onDestroy() %7B%0A        super.onDestroy();%0A        mQuery.onCompleted();
 %0A    %7D%0A%0A
@@ -5294,345 +5294,26 @@
    m
-Ctrl.queryEntries(input)%0A                    .observeOn(AndroidSchedulers.mainThread())%0A                    .subscribe(%0A                            (entry) -%3E mAdapter.addItem(entry.wordStr, SelectorAdapter.Type.B),%0A                            (e) -%3E e.printStackTrace(),%0A                            () -%3E mAdapter.notifyDataSetChanged()
+Query.onNext(input
 );%0A 

use debounce to prevent redundant query if user input too quick