package com.mmjang.ankihelper.ui.popup;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.net.wifi.hotspot2.omadm.PpsMoParser;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.support.annotation.RequiresApi;
import android.support.design.chip.Chip;
import android.support.design.chip.ChipGroup;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.ActionMode;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.ichi2.anki.FlashCardsContract;
import com.ichi2.anki.api.NoteInfo;
import com.mmjang.ankihelper.MyApplication;
import com.mmjang.ankihelper.R;
import com.mmjang.ankihelper.anki.AnkiDroidHelper;
import com.mmjang.ankihelper.data.Settings;
import com.mmjang.ankihelper.data.database.ExternalDatabase;
import com.mmjang.ankihelper.data.dict.BingImage;
import com.mmjang.ankihelper.data.dict.Definition;
import com.mmjang.ankihelper.data.dict.DictionaryDotCom;
import com.mmjang.ankihelper.data.dict.DictionaryRegister;
import com.mmjang.ankihelper.data.dict.Dub91Sentence;
import com.mmjang.ankihelper.data.dict.EudicSentence;
import com.mmjang.ankihelper.data.dict.IDictionary;
import com.mmjang.ankihelper.data.dict.RenRenCiDianSentence;
import com.mmjang.ankihelper.data.dict.SolrDictionary;
import com.mmjang.ankihelper.data.dict.UrbanAutoCompleteAdapter;
import com.mmjang.ankihelper.data.dict.VocabCom;
import com.mmjang.ankihelper.data.history.HistoryUtil;
import com.mmjang.ankihelper.data.model.UserTag;
import com.mmjang.ankihelper.data.plan.OutputPlan;
import com.mmjang.ankihelper.data.plan.OutputPlanPOJO;
import com.mmjang.ankihelper.domain.CBWatcherService;
import com.mmjang.ankihelper.domain.PlayAudioManager;
import com.mmjang.ankihelper.domain.PronounceManager;
import com.mmjang.ankihelper.ui.LauncherActivity;
import com.mmjang.ankihelper.ui.plan.PlanEditorActivity;
import com.mmjang.ankihelper.ui.widget.BigBangLayout;
import com.mmjang.ankihelper.ui.widget.BigBangLayoutWrapper;
import com.mmjang.ankihelper.util.Constant;
import com.mmjang.ankihelper.util.FieldUtil;
import com.mmjang.ankihelper.util.RegexUtil;
import com.mmjang.ankihelper.util.TextSplitter;
import com.mmjang.ankihelper.util.Translator;
import com.mmjang.ankihelper.util.Utils;
import com.tonyodev.fetch2.Download;
import com.tonyodev.fetch2.Error;
import com.tonyodev.fetch2.Fetch;
import com.tonyodev.fetch2.FetchConfiguration;
import com.tonyodev.fetch2.FetchListener;
import com.tonyodev.fetch2.NetworkType;
import com.tonyodev.fetch2.Priority;
import com.tonyodev.fetch2.Request;
import com.tonyodev.fetch2core.DownloadBlock;
import com.tonyodev.fetch2core.Func;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.litepal.crud.DataSupport;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import me.everything.android.ui.overscroll.OverScrollDecoratorHelper;

import static com.mmjang.ankihelper.util.FieldUtil.getBlankSentence;
import static com.mmjang.ankihelper.util.FieldUtil.getBoldSentence;
import static com.mmjang.ankihelper.util.FieldUtil.getNormalSentence;


public class PopupActivity extends Activity implements BigBangLayoutWrapper.ActionListener{

    List<IDictionary> dictionaryList;
    IDictionary currentDicitonary;
    List<OutputPlanPOJO> outputPlanList;
    List<String> languageList;
    OutputPlanPOJO currentOutputPlan;
    Settings settings;
    String mTextToProcess;
    String mPlanNameFromIntent;
    String mCurrentKeyWord;
    TextSplitter mTextSplitter;
    String mNoteEditedByUser = "";
    Set<String> mTagEditedByUser = new HashSet<>();
    //posiblle pre set target word
    String mTargetWord;
    //possible url from dedicated borwser
    String mUrl = "";
    //possible specific note id to update
    Long mUpdateNoteId = 0L;
    //!!!!!!!!!!!important!!! boolean, if the plan spinner is during init, forbid asyncsearch;
    boolean isDuringPlanSpinnerInit = false;
    //update action   replace/append    append is the default action, to prevent data loss;
    String mUpdateAction;
    //possible bookmark id from fbreader
    String mFbReaderBookmarkId;
    //translation
    String mTranslatedResult = "";
    boolean needTranslation = false;
    //views
    AutoCompleteTextView act;
    Button btnSearch;
    ImageButton btnPronounce;
    Spinner planSpinner;
    Spinner pronounceLanguageSpinner;
    //RecyclerView recyclerViewDefinitionList;
    ImageButton mBtnEditNote;
    ImageButton mBtnEditTag;
    ImageButton mBtnTranslation;
    ImageButton mBtnFooterRotateLeft;
    ImageButton mBtnFooterRotateRight;
    ImageButton mBtnFooterScrollup;
    ProgressBar progressBar;
    ProgressBar mAudioProgress;

    CardView mCardViewTranslation;
    EditText mEditTextTranslation;
    //fab
    //FloatingActionButton mFab;
    ScrollView scrollView;
    //plan b
    LinearLayout viewDefinitionList;
    List<Definition> mDefinitionList;
    //media
    MediaPlayer mMediaPlayer;
    //downloader
    Fetch fetch;
    boolean isFetchDownloading = false;
    //async event
    private static final int PROCESS_DEFINITION_LIST = 1;
    private static final int ASYNC_SEARCH_FAILED = 2;
    private static final int TRANSLATION_DONE = 3;
    private static final int TRANSLATIOn_FAILED = 4;

    //view tag
    private static final int TAG_NOTE_ID_LONG = 5;
    //async
    @SuppressLint("HandlerLeak")
    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PROCESS_DEFINITION_LIST:
                    showSearchButton();
                    //scrollView.fullScroll(ScrollView.FOCUS_UP);
                    mDefinitionList = (List<Definition>) msg.obj;
                    processDefinitionList(mDefinitionList);
                    break;
                case ASYNC_SEARCH_FAILED:
                    showSearchButton();
                    Toast.makeText(PopupActivity.this, (String) msg.obj, Toast.LENGTH_LONG).show();
                    break;
                case TRANSLATION_DONE:
                    String result = (String) msg.obj;
                    String[] splitted = result.split("\n");
                    if(splitted.length > 0 && splitted[0].equals("error")){
                        Toast.makeText(PopupActivity.this, result, Toast.LENGTH_SHORT).show();
                        break;
                    }
                    mEditTextTranslation.setText((result));
                    showTranslateDone();
                    showTranslationCardView(true);
                    break;
                default:
                    showTranslateNormal();
                    Toast.makeText(PopupActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
    private BigBangLayout bigBangLayout;
    private BigBangLayoutWrapper bigBangLayoutWrapper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if(Settings.getInstance(this).getPinkThemeQ()){
            setTheme(R.style.TransparentPink);
        }
        super.onCreate(savedInstanceState);
        setStatusBarColor();
        setContentView(R.layout.activity_popup);
//        getActionBar().hide();
        //set animation
        overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
        scrollView = (ScrollView) findViewById(R.id.scrollView);
        OverScrollDecoratorHelper.setUpOverScroll(scrollView);
        //
        assignViews();
        initBigBangLayout();
        loadData(); //dictionaryList;
        populatePlanSpinner();
        populateLanguageSpinner();
        setEventListener();
        if (settings.getMoniteClipboardQ()) {
            startCBService();
        }

        handleIntent();

        //async invoke droid
        asyncInvokeDroid();
    }

    private void asyncInvokeDroid() {
        new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        try{
                            MyApplication.getAnkiDroid().getApi().getDeckList();
                        }catch (Exception e){
                        }
                    }
                }
        ).start();
    }

    private void setTargetWord(){
        if (!TextUtils.isEmpty(mTargetWord)) {
            for (BigBangLayout.Line line : bigBangLayout.getLines()) {
                List<BigBangLayout.Item> items = line.getItems();
                for (BigBangLayout.Item item : items) {
                    if (item.getText().equals(mTargetWord)) {
                        item.setSelected(true);
                    }
                }
            }
            act.setText(mTargetWord);
            asyncSearch(mTargetWord);
        }else{
            if(mTextToProcess.matches("[a-zA-Z\\-]*")){
                act.setText(mTextToProcess);
                asyncSearch(mTextToProcess);
            }
        }
    }

    private void setStatusBarColor() {
        int statusBarColor = 0;
        if (Build.VERSION.SDK_INT >= 21) {
            statusBarColor = getWindow().getStatusBarColor();
        }
        if (Build.VERSION.SDK_INT >= 21) {
            getWindow().setStatusBarColor(statusBarColor);
        }
    }

    private void assignViews() {
        act = (AutoCompleteTextView) findViewById(R.id.edit_text_hwd);
        btnSearch = (Button) findViewById(R.id.btn_search);
        btnPronounce = ((ImageButton) findViewById(R.id.btn_pronounce));
        planSpinner = (Spinner) findViewById(R.id.plan_spinner);
        pronounceLanguageSpinner = (Spinner) findViewById(R.id.language_spinner);
        //recyclerViewDefinitionList = (RecyclerView) findViewById(R.id.recycler_view_definition_list);
        viewDefinitionList = (LinearLayout) findViewById(R.id.view_definition_list);
        mBtnEditNote = (ImageButton) findViewById(R.id.footer_note);
        mBtnEditTag = (ImageButton) findViewById(R.id.footer_tag);
        progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        bigBangLayout = (BigBangLayout) findViewById(R.id.bigbang);
        bigBangLayoutWrapper = (BigBangLayoutWrapper) findViewById(R.id.bigbang_wrapper);
        mCardViewTranslation = (CardView) findViewById(R.id.cardview_translation);
        mBtnTranslation = (ImageButton) findViewById(R.id.footer_translate);
        mEditTextTranslation = (EditText) findViewById(R.id.edittext_translation);
        //mFab = (FloatingActionButton) findViewById(R.id.fab);
        mBtnFooterRotateLeft = (ImageButton) findViewById(R.id.footer_rotate_left);
        mBtnFooterRotateRight= (ImageButton) findViewById(R.id.footer_rotate_right);
        mBtnFooterScrollup = (ImageButton) findViewById(R.id.footer_scroll_up);
        mAudioProgress = findViewById(R.id.audio_progress);
    }

    private void loadData() {
        dictionaryList = DictionaryRegister.getDictionaryObjectList();
        outputPlanList = ExternalDatabase.getInstance().getAllPlan();
        settings = Settings.getInstance(this);
        //load tag
        boolean loadQ = settings.getSetAsDefaultTag();
        if (loadQ) {
            mTagEditedByUser = Utils.fromStringToTagSet(settings.getDefaulTag());
        }
        //check if outputPlanList is empty
        if(outputPlanList.size() == 0){
            //Toast.makeText(this, , Toast.LENGTH_LONG).show();
            Utils.showMessage(this, getResources().getString(R.string.toast_no_available_plan));
        }
    }

    private void populatePlanSpinner() {
        if(outputPlanList.size() == 0){
            return;
        }
        final String[] planNameArr = new String[outputPlanList.size()];
        for (int i = 0; i < outputPlanList.size(); i++) {
            planNameArr[i] = outputPlanList.get(i).getPlanName();
        }
        ArrayAdapter<String> planSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_item, planNameArr);
        planSpinner.setAdapter(planSpinnerAdapter);
        planSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //set plan to last selected plan
        String lastSelectedPlan = settings.getLastSelectedPlan();
        if (lastSelectedPlan.equals("")) //first use, set default plan to first one if any
        {
            if (outputPlanList.size() > 0) {
                settings.setLastSelectedPlan(outputPlanList.get(0).getPlanName());
                currentOutputPlan = outputPlanList.get(0);
                currentDicitonary = getDictionaryFromOutputPlan(currentOutputPlan);
                if(currentDicitonary == null){
                    String message = String.format("方案\"%s\"所选词典\"%s\"不存在,请检查是否需要重新导入自定义词典",
                            currentOutputPlan.getPlanName(),
                            currentOutputPlan.getDictionaryKey());
                    Utils.showMessage(PopupActivity.this, message);
                }else {
                    setActAdapter(currentDicitonary);
                }
            } else {
                return ;
            }
        }

        ///////////////if user add intent parameter to control which plan to use
        mPlanNameFromIntent = getIntent().getStringExtra(Constant.INTENT_ANKIHELPER_PLAN_NAME);
        if(mPlanNameFromIntent != null){
            lastSelectedPlan = mPlanNameFromIntent;
        }
        ///////////////
        int i = 0;
        boolean find = false;
        for (OutputPlanPOJO plan : outputPlanList) {
            if (plan.getPlanName().equals(lastSelectedPlan)) {
                isDuringPlanSpinnerInit = true;
                planSpinner.setSelection(i);
                currentOutputPlan = outputPlanList.get(i);
                currentDicitonary = getDictionaryFromOutputPlan(currentOutputPlan);
                if(currentDicitonary == null) {
                    String message = String.format("方案\"%s\"所选词典\"%s\"不存在,请检查是否需要重新导入自定义词典",
                            currentOutputPlan.getPlanName(),
                            currentOutputPlan.getDictionaryKey());
                    Utils.showMessage(PopupActivity.this, message);
                    break;
                }
                setActAdapter(currentDicitonary);
                find = true;
                break;
            }
            //if not equal, compare next
            i++;
        }
        if (!find) //if the saved last plan no longer in the plan list, reset to first one
        {
            if (outputPlanList.size() > 0) {
                settings.setLastSelectedPlan(outputPlanList.get(0).getPlanName());
                currentOutputPlan = outputPlanList.get(0);
                currentDicitonary = getDictionaryFromOutputPlan(currentOutputPlan);
                if(currentDicitonary == null) {
                    String message = String.format("方案\"%s\"所选词典\"%s\"不存在,请检查是否需要重新导入自定义词典",
                            currentOutputPlan.getPlanName(),
                            currentOutputPlan.getDictionaryKey());
                    Utils.showMessage(PopupActivity.this, message);
                }
                setActAdapter(currentDicitonary);
            }
        } else {
            //if find, then current plan and dictionary must have been set above.
        }

//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//            scrollView.setOnScrollChangeListener(
//                    new View.OnScrollChangeListener() {
//                        @Override
//                        public void onScrollChange(View view, int i, int i1, int i2, int i3) {
//                            if(i1 > i3){
//                                mFab.hide();
//                            }else{
//                                mFab.show();
//                                //mFab.setAlpha(Constant.FLOAT_ACTION_BUTTON_ALPHA);
//                            }
//                        }
//                    }
//            );
//        }
    }

    private void populateLanguageSpinner() {

        String[] languages = PronounceManager.getAvailablePronounceLanguage();
        ArrayAdapter<String> languagesSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_item, languages);
        languagesSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        pronounceLanguageSpinner.setAdapter(languagesSpinnerAdapter);
        int lastPronounceLanguageIndex = settings.getLastPronounceLanguage();
        pronounceLanguageSpinner.setSelection(lastPronounceLanguageIndex);

    }

    private void initBigBangLayout(){
        bigBangLayout.setShowSymbol(true);
        bigBangLayout.setShowSpace(true);
        bigBangLayout.setShowSection(true);
        bigBangLayout.setItemSpace(0);
        bigBangLayout.setLineSpace(0);
        bigBangLayout.setTextPadding(5);
        bigBangLayout.setTextPaddingPort(5);
        bigBangLayoutWrapper.setStickHeader(true);
        bigBangLayoutWrapper.setActionListener(this);

    }

    private void setEventListener() {

        //auto finish
        Button btnCancelBlank = (Button) findViewById(R.id.btn_cancel_blank);
        Button btnCancelBlankAboveCard = (Button) findViewById(R.id.btn_cancel_blank_above_card);
        btnCancelBlank.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        finish();
                    }
                }
        );
        btnCancelBlankAboveCard.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        finish();
                    }
                }
        );

        planSpinner.setOnItemSelectedListener(
                new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                        currentOutputPlan = outputPlanList.get(position);
                        currentDicitonary = getDictionaryFromOutputPlan(currentOutputPlan);
                        setActAdapter(currentDicitonary);
                        //memorise last selected plan
                        settings.setLastSelectedPlan(currentOutputPlan.getPlanName());
                        String actContent = act.getText().toString();

                        if(isDuringPlanSpinnerInit){
                            isDuringPlanSpinnerInit = false;
                        }else {
                            if(!actContent.trim().isEmpty()) {
                                asyncSearch(actContent);
                            }
                        }
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {

                    }
                }
        );

        pronounceLanguageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
                settings.setLastPronounceLanguage(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

        btnSearch.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        final String word = act.getText().toString();
                        if (!word.isEmpty()) {
                            asyncSearch(word);
                            Utils.hideSoftKeyboard(PopupActivity.this);
                        }
                    }
                }
        );

        btnPronounce.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String word = act.getText().toString();
                PlayAudioManager.playPronounceVoice(PopupActivity.this, word);
            }
        });

        mBtnEditNote.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setupEditNoteDialog();
                    }
                }
        );

        mBtnEditTag.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setupEditTagDialog();
                    }
                }
        );

        act.setOnItemClickListener(
                new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                        Log.d("autocomplete", i + "");
                        act.post(
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        btnSearch.callOnClick();
                                    }
                                }
                        );
                    }
                }
        );

        mBtnTranslation.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(mEditTextTranslation.getText().toString().equals("")){
                            asyncTranslate(mTextToProcess);
                        }
                    }
                }
        );
        mBtnFooterRotateRight.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        int mPlanSize = outputPlanList.size();
                        int currentPos = planSpinner.getSelectedItemPosition();
                        if(mPlanSize > 1){
                            if(currentPos < mPlanSize - 1){
                                planSpinner.setSelection(currentPos + 1);
                            }
                            else if(currentPos == mPlanSize - 1){
                                planSpinner.setSelection(0);
                            }
                            //vibarate(Constant.VIBRATE_DURATION);
                            //scrollView.fullScroll(ScrollView.FOCUS_UP);
                        }else{
                            Toast.makeText(PopupActivity.this, R.string.str_only_one_plan_cant_switch, Toast.LENGTH_SHORT).show();
                        }
                    }
                }
        );

        mBtnFooterRotateLeft.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        int mPlanSize = outputPlanList.size();
                        int currentPos = planSpinner.getSelectedItemPosition();
                        if(mPlanSize > 1){
                            if(currentPos > 0){
                                planSpinner.setSelection(currentPos - 1);
                            }
                            else if(currentPos == 0){
                                planSpinner.setSelection(mPlanSize - 1);
                            }
                        //    vibarate(Constant.VIBRATE_DURATION);
                            //scrollView.fullScroll(ScrollView.FOCUS_UP);
                        }else{
                            Toast.makeText(PopupActivity.this, R.string.str_only_one_plan_cant_switch, Toast.LENGTH_SHORT).show();
                        }
                    }
                }
        );

        mBtnFooterScrollup.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(scrollView.getScrollY() > 0) {
                            scrollView.fullScroll(ScrollView.FOCUS_UP);
                        }
                    }
                }
        );
    }

    private IDictionary getDictionaryFromOutputPlan(OutputPlanPOJO outputPlan) {
        String dictionaryName = outputPlan.getDictionaryKey();
        for (IDictionary dict : dictionaryList) {
            if (dict.getDictionaryName().equals(dictionaryName)) {
                return dict;
            }
        }
        return null;
    }

    private void processDefinitionList(List<Definition> definitionList) {
        if (definitionList.isEmpty()) {
            Toast.makeText(this, R.string.definition_not_found, Toast.LENGTH_SHORT).show();
        } else {
//            DefinitionAdapter defAdapter = new DefinitionAdapter(PopupActivity.this, definitionList, mTextSplitter, currentOutputPlan);
//            LinearLayoutManager llm = new LinearLayoutManager(this);
//            //llm.setAutoMeasureEnabled(true);
//            recyclerViewDefinitionList.setLayoutManager(llm);
//            //recyclerViewDefinitionList.getRecycledViewPool().setMaxRecycledViews(0,0);
//            //recyclerViewDefinitionList.setHasFixedSize(true);
//            //recyclerViewDefinitionList.setNestedScrollingEnabled(false);
//            recyclerViewDefinitionList.setAdapter(defAdapter);
            viewDefinitionList.removeAllViewsInLayout();
            for (Definition def : definitionList) {
                viewDefinitionList.addView(getCardFromDefinition(def));
            }
            viewDefinitionList.post(
                    new Runnable() {
                        @Override
                        public void run() {
                            if(scrollView.getScrollY() > 10) {
                                //scrollView.fullScroll(ScrollView.FOCUS_UP);
                            }
                        }
                    }
            );
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(isFromAndroidQClipboard) {
            if (!Settings.getInstance(MyApplication.getContext()).getMoniteClipboardQ()) {
                return;
            }
            ClipboardManager cb = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
            if (cb.hasPrimaryClip()) {
                if (cb.hasText()) {
                    String text = cb.getText().toString();
                    mTextToProcess = text;
                }
            }
            populateWordSelectBox();
            bigBangLayout.post( new Runnable() {
                @Override
                public void run() {
                    setTargetWord();
                    if(Utils.containsTranslationField(currentOutputPlan)){
                        asyncTranslate(mTextToProcess);
                    }
                }
            });
        }
    }

    boolean isFromAndroidQClipboard = false;
    private void handleIntent() {
        Intent intent = getIntent();
        String action = intent.getAction();
        String type = intent.getType();
        if (intent == null) {
            return;
        }
        if (type == null) {
            return;
        }
        //getStringExtra() may return null
        if (Intent.ACTION_SEND.equals(action) && type.equals("text/plain")) {
            String base64 = intent.getStringExtra(Constant.INTENT_ANKIHELPER_BASE64);
            mTextToProcess = intent.getStringExtra(Intent.EXTRA_TEXT);
            if(mTextToProcess != null && mTextToProcess.equals(Constant.USE_CLIPBOARD_CONTENT_FLAG)){
                mTextToProcess = "";
                isFromAndroidQClipboard = true;
            }
            if(base64 != null && !base64.equals("0")){
                mTextToProcess = new String(Base64.decode(mTextToProcess, Base64.DEFAULT));
            }
            mTargetWord = intent.getStringExtra(Constant.INTENT_ANKIHELPER_TARGET_WORD);
            mUrl = intent.getStringExtra(Constant.INTENT_ANKIHELPER_TARGET_URL);
            //mFbReaderBookmarkId = intent.getStringExtra(Constant.INTENT_ANKIHELPER_FBREADER_BOOKMARK_ID);
            String noteEditedByUser = intent.getStringExtra(Constant.INTENT_ANKIHELPER_NOTE);
            if(noteEditedByUser != null){
                mNoteEditedByUser = noteEditedByUser;
            }
            String updateId = intent.getStringExtra(Constant.INTENT_ANKIHELPER_NOTE_ID);
            mUpdateAction = intent.getStringExtra(Constant.INTENT_ANKIHELPER_UPDATE_ACTION);
            if(updateId != null && !updateId.isEmpty())
            {
                    try{
                        mUpdateNoteId = Long.parseLong(updateId);
                        if(mUpdateNoteId > 0){
                            mTagEditedByUser =
                                    MyApplication.getAnkiDroid()
                                            .getApi().getNote(mUpdateNoteId)
                                            .getTags();
                        }
                    }
                    catch(Exception e){

                    }
        }
}
        if (Intent.ACTION_PROCESS_TEXT.equals(action) && type.equals("text/plain")) {
                mTextToProcess = intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT);
                }
                if (mTextToProcess == null) {
            return;
        }
        populateWordSelectBox();

        HistoryUtil.savePopupOpen(mTextToProcess);

        bigBangLayout.post( new Runnable() {
            @Override
            public void run() {
                setTargetWord();
                if(Utils.containsTranslationField(currentOutputPlan)){
                    asyncTranslate(mTextToProcess);
                }
            }
        });
    }

    private void populateWordSelectBox() {
        List<String> localSegments = TextSplitter.getLocalSegments(mTextToProcess);
        bigBangLayout.removeAllViews();
        for (String localSegment : localSegments) {
            bigBangLayout.addTextItem(localSegment);
        }
        bigBangLayout.post(
                new Runnable() {
                    @Override
                    public void run() {
                        String currentWord = FieldUtil.getSelectedText(bigBangLayout.getLines());
                        if (!currentWord.equals("")&&!currentWord.equals(act.getText().toString())) {
                            mCurrentKeyWord = currentWord;
                            act.setText(currentWord);
                            asyncSearch(currentWord);
                        }
                    }
                }
        );
    }


    private void asyncSearch(final String word) {
        if (word.length() == 0) {
            showPronounce(false);
            return;
        }
        if(currentDicitonary == null || currentOutputPlan == null){
            return;
        }
        showProgressBar();
        progressBar.invalidate();
        showPronounce(true);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //Your code goes here
                    Log.d("clicked", "yes");
                    List<Definition> d = currentDicitonary.wordLookup(word);
                    Message message = mHandler.obtainMessage();
                    message.obj = d;
                    message.what = PROCESS_DEFINITION_LIST;
                    mHandler.sendMessage(message);
                } catch (Exception e) {
                    String error = e.getMessage();
                    Message message = mHandler.obtainMessage();
                    message.obj = error;
                    message.what = ASYNC_SEARCH_FAILED;
                    mHandler.sendMessage(message);
                }
            }
        });
        thread.start();
        HistoryUtil.saveWordlookup(mTextToProcess, word);
    }

    private void asyncTranslate(final String mTextToProcess){
        if(mTextToProcess == null) return;
        if(mTextToProcess.trim().equals("")) return;
        showTranslateLoading();
        Thread thread = new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        try{
                            String result;
                            if(RegexUtil.isChineseSentence(mTextToProcess)){
                                result = Translator.translate(mTextToProcess, "zh", "en");
                            }else {
                                result = Translator.translate(mTextToProcess, "auto", "zh");
                            }
                            Message message = mHandler.obtainMessage();
                            message.obj = result;
                            message.what = TRANSLATION_DONE;
                            mHandler.sendMessage(message);
                        }
                        catch(Exception e){
                            String error = e.getMessage();
                            Message message = mHandler.obtainMessage();
                            message.obj = error;
                            message.what = TRANSLATIOn_FAILED;
                            mHandler.sendMessage(message);
                        }
                    }
                }
        );
        thread.start();
    }

    private void setActAdapter(IDictionary dict) {
        Object adapter = dict.getAutoCompleteAdapter(PopupActivity.this,
                android.R.layout.simple_spinner_dropdown_item);
        if(adapter != null){
            if(adapter instanceof SimpleCursorAdapter){
                act.setAdapter((SimpleCursorAdapter) adapter);
            }
            else if(adapter instanceof UrbanAutoCompleteAdapter){
                act.setAdapter((UrbanAutoCompleteAdapter) adapter);
            }
        }
        act.setOnFocusChangeListener(
                new View.OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                        if(hasFocus){
                            if(act.getText().toString().trim().isEmpty()){
                                return;
                            }
                            act.showDropDown();
                        }
                    }
                }
        );
    }

    //plan B
    private View getCardFromDefinition(final Definition def) {
        View view;
        if(settings.getLeftHandModeQ()){
            view = LayoutInflater.from(PopupActivity.this)
                    .inflate(R.layout.definition_item_left, null);
        }
        else{
            view = LayoutInflater.from(PopupActivity.this)
                    .inflate(R.layout.definition_item, null);
        }
        //toggle fab with clicks
//        view.setOnClickListener(
//                new View.OnClickListener() {
//                    @Override
//                    public void onClick(View view) {
//                        if(mFab.getVisibility() == View.VISIBLE){
//                            mFab.hide();
//                        }else{
//                            mFab.show();
//                        }
//                    }
//                }
//        );
        final TextView textVeiwDefinition = (TextView) view.findViewById(R.id.textview_definition);
        final ImageButton btnAddDefinition = (ImageButton) view.findViewById(R.id.btn_add_definition);
        final LinearLayout btnAddDefinitionLarge = (LinearLayout) view.findViewById(R.id.btn_add_definition_large);
        final ImageView defImage = view.findViewById(R.id.def_img);
        btnAddDefinitionLarge.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        btnAddDefinition.callOnClick();
                    }
                }
        );
        //final Definition def = mDefinitionList.get(position);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            textVeiwDefinition.setText(Html.fromHtml(def.getDisplayHtml(), Html.FROM_HTML_MODE_COMPACT));
        }
        else{
            textVeiwDefinition.setText(Html.fromHtml(def.getDisplayHtml()));

        }

        if(def.getDisplayHtml().isEmpty()){
            textVeiwDefinition.setVisibility(View.GONE);
        }

        if(def.getImageUrl()!=null && !def.getImageUrl().isEmpty()){
            Glide.with(this).load(def.getImageUrl()).into(defImage);
            defImage.setVisibility(View.VISIBLE);
        }

        if((currentDicitonary instanceof EudicSentence ||
                currentDicitonary instanceof SolrDictionary ||
                currentDicitonary instanceof RenRenCiDianSentence) && def.getAudioUrl()!=null && !def.getAudioUrl().isEmpty()){
            textVeiwDefinition.setTextIsSelectable(false);
            textVeiwDefinition.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (mMediaPlayer == null) {
                                mMediaPlayer = new MediaPlayer();
                                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                                mMediaPlayer.setOnPreparedListener(
                                        new MediaPlayer.OnPreparedListener() {
                                            @Override
                                            public void onPrepared(MediaPlayer mp) {
                                                mMediaPlayer.start();
                                                mAudioProgress.setVisibility(View.GONE);
                                            }
                                        }
                                );
                            }
                            try {
                                if(mMediaPlayer.isPlaying()) {
                                    mMediaPlayer.reset();
                                    //mMediaPlayer.release();
                                }
                            }catch(IllegalStateException e){

                            }
                            try {
                                mMediaPlayer.setDataSource(PopupActivity.this, Uri.parse(def.getAudioUrl()));
                                mAudioProgress.setVisibility(View.VISIBLE);
                                mMediaPlayer.prepareAsync();
                            } catch (IOException e) {
                                e.printStackTrace();
                                Toast.makeText(PopupActivity.this, e.getMessage(), Toast.LENGTH_SHORT);
                            } catch (IllegalStateException e){

                            }
//                            mMediaPlayer.setOnPreparedListener(
//                                    new MediaPlayer.OnPreparedListener() {
//                                        @Override
//                                        public void onPrepared(MediaPlayer mp) {
//                                        }
//                                    }
//                            );

                            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                                @Override
                                public void onCompletion(MediaPlayer mp) {
                                    mp.reset();
                                    mAudioProgress.setVisibility(View.GONE);
                                }
                            });

                            mMediaPlayer.setOnErrorListener(
                                    new MediaPlayer.OnErrorListener() {
                                        @Override
                                        public boolean onError(MediaPlayer mp, int what, int extra) {
                                            mp.reset();
                                            Toast.makeText(PopupActivity.this, "Failed to play audio, check your connection.", Toast.LENGTH_SHORT);
                                            mAudioProgress.setVisibility(View.GONE);
                                            return false;
                                        }
                                    }
                            );
//                            if(mMediaPlayer == null){
//                                mMediaPlayer = new MediaPlayer();
//                            }
//
//                            try {
//                                if(mMediaPlayer.isPlaying()) {
//                                    mMediaPlayer.reset();
//                                    //mMediaPlayer.release();
//                                }
//                            }catch(IllegalStateException e){
//
//                            }
//                            try {
//                                Toast.makeText(PopupActivity.this, "Loading...", Toast.LENGTH_SHORT).show();
//                                mMediaPlayer.setDataSource(PopupActivity.this, Uri.parse(def.getAudioUrl()));
//                                mMediaPlayer.prepare();
//                                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
//                                    @Override
//                                    public void onCompletion(MediaPlayer mp) {
//                                        mMediaPlayer.reset();
//                                        //mMediaPlayer.release();
//                                    }
//                                });
//                                mMediaPlayer.start();
//                            } catch (IOException e) {
//                                e.printStackTrace();
//                                Toast.makeText(PopupActivity.this, "Failed to play audio", Toast.LENGTH_SHORT).show();
//                            }
                        }
                    }
            );
        }

        //set custom action for the textView
        makeTextViewSelectAndSearch(textVeiwDefinition);
        //holder.itemView.setAnimation(AnimationUtils.loadAnimation(mActivity, android.R.anim.fade_in));
        //holder.textVeiwDefinition.setTextColor(Color.BLACK);
        btnAddDefinition.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //vibarate(Constant.VIBRATE_DURATION);
                        //before add, check if this note is already added by check the attached tag
                        try {
                            Long noteIdAdded = (Long) btnAddDefinition.getTag(R.id.TAG_NOTE_ID);
                            if (noteIdAdded != null) {
                                if (mUpdateNoteId == 0) {
                                    if (Utils.deleteNote(PopupActivity.this, noteIdAdded.longValue())) {
                                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                            btnAddDefinition.setBackground(ContextCompat.getDrawable(
                                                    PopupActivity.this,
                                                    Utils.getResIdFromAttribute(PopupActivity.this, R.attr.icon_add)));
                                        }
                                        btnAddDefinition.setTag(R.id.TAG_NOTE_ID, null);
                                        Toast.makeText(PopupActivity.this, R.string.str_cancel_note_add, Toast.LENGTH_SHORT).show();

                                    } else {
                                        Toast.makeText(PopupActivity.this, R.string.error_note_cancel, Toast.LENGTH_SHORT).show();
                                    }
                                } else {
                                    Toast.makeText(PopupActivity.this, R.string.str_not_cancelable_append_mode, Toast.LENGTH_SHORT).show();
                                }
                                return;
                            }

                            //save image
                            if (def.getImageUrl() != null && !def.getImageUrl().isEmpty()) {
                                if (defImage.getDrawable() != null &&
                                        (currentDicitonary instanceof BingImage ||
                                                currentDicitonary instanceof RenRenCiDianSentence ||
                                                currentDicitonary instanceof Dub91Sentence)) {
                                    BitmapDrawable drawable = (BitmapDrawable) defImage.getDrawable();
                                    Bitmap bm = drawable.getBitmap();

                                    OutputStream fOut = null;
                                    //Uri outputFileUri;
                                    try {
                                        File root = new File(Constant.IMAGE_MEDIA_DIRECTORY);
                                        if (!root.exists()) {
                                            root.mkdirs();
                                        }
                                        File sdImageMainDirectory = new File(root, def.getImageName());
                                        //outputFileUri = Uri.fromFile(sdImageMainDirectory);
                                        fOut = new FileOutputStream(sdImageMainDirectory);
                                    } catch (Exception e) {

                                    }
                                    try {
                                        bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
                                        fOut.flush();
                                        fOut.close();
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                            ///////////////////////////////////

                            AnkiDroidHelper mAnkiDroid = MyApplication.getAnkiDroid();
                            String[] sharedExportElements = Constant.getSharedExportElements();
                            String[] exportFields = new String[currentOutputPlan.getFieldsMap().size()];
                            int i = 0;
                            Map<String, String> map = currentOutputPlan.getFieldsMap();
                            for (String exportedFieldKey : currentOutputPlan.getFieldsMap().values()) {
                                if (exportedFieldKey.equals(sharedExportElements[0])) {
                                    exportFields[i] = "";
                                    i++;
                                    continue;
                                }

                                if (exportedFieldKey.equals(sharedExportElements[1])) {
                                    exportFields[i] = getNormalSentence(bigBangLayout.getLines());
                                    i++;
                                    continue;
                                }

                                if (exportedFieldKey.equals(sharedExportElements[2])) {
                                    exportFields[i] = getBoldSentence(bigBangLayout.getLines());
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[3])) {
                                    exportFields[i] = getBlankSentence(bigBangLayout.getLines(), true);
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[4])) {
                                    exportFields[i] = getBlankSentence(bigBangLayout.getLines(), false);
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[5])) {
                                    exportFields[i] = mNoteEditedByUser;
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[6])) {
                                    exportFields[i] = mUrl;
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[7])) {
                                    exportFields[i] = Utils.getAllHtmlFromDefinitionList(mDefinitionList);
                                    i++;
                                    continue;
                                }
                                if (exportedFieldKey.equals(sharedExportElements[8])) {
                                    exportFields[i] = mEditTextTranslation.getText().toString().replace("\n", "<br/>");
                                    i++;
                                    continue;
                                }
//                            if(exportedFieldKey.equals(sharedExportElements[5])){
//                                if(mFbReaderBookmarkId != null){
//                                    exportFields[i] = String.format(Constant.FBREADER_URL_TMPL, mFbReaderBookmarkId);
//                                }else{
//                                    exportFields[i]="";
//                                }
//                                i++;
//                                continue;
//                            }
                                if (def.hasElement(exportedFieldKey)) {
                                    exportFields[i] = def.getExportElement(exportedFieldKey);
                                    i++;
                                    continue;
                                }

                                exportFields[i] = "";
                                i++;
                            }
                            //handle download; audio or image
                            if (currentDicitonary instanceof EudicSentence ||
                                    currentDicitonary instanceof RenRenCiDianSentence) {
                                if (fetch == null) {
                                    initFetch();
                                }
                                if (map.containsValue("原声例句")) {
                                    final Request request = new Request(def.getAudioUrl(), Constant.AUDIO_MEDIA_DIRECTORY + def.getAudioName());
                                    request.setPriority(Priority.HIGH);
                                    request.setNetworkType(NetworkType.ALL);
                                    isFetchDownloading = true;
                                    fetch.enqueue(request,
                                            new Func<Request>() {
                                                @Override
                                                public void call(@NotNull Request result) {
                                                    mAudioProgress.setVisibility(View.VISIBLE);
                                                    //                                isFetchDownloading = true;
                                                }
                                            }
                                            ,
                                            new Func<Error>() {
                                                @Override
                                                public void call(@NotNull Error result) {
                                                    isFetchDownloading = false;
                                                }
                                            }
                                    );
                                }
                            }

                            if (currentDicitonary instanceof SolrDictionary) {
                                if (fetch == null) {
                                    initFetch();
                                }
                                if (!def.getAudioUrl().isEmpty() && (map.containsValue("音频") || map.containsValue("复合项"))) {
                                    final Request request = new Request(def.getAudioUrl(), Constant.AUDIO_MEDIA_DIRECTORY + def.getAudioName());
                                    request.setPriority(Priority.HIGH);
                                    request.setNetworkType(NetworkType.ALL);
                                    isFetchDownloading = true;
                                    fetch.enqueue(request,
                                            new Func<Request>() {
                                                @Override
                                                public void call(@NotNull Request result) {
                                                    mAudioProgress.setVisibility(View.VISIBLE);
                                                    isFetchDownloading = true;
                                                }
                                            }
                                            ,
                                            new Func<Error>() {
                                                @Override
                                                public void call(@NotNull Error result) {
                                                    isFetchDownloading = false;
                                                }
                                            }
                                    );
                                }
                            }

                            if (currentDicitonary instanceof VocabCom) {
                                if (fetch == null) {
                                    initFetch();
                                }
                                if (map.containsValue("离线发音")) {
                                    final Request request = new Request(def.getAudioUrl(), Constant.AUDIO_MEDIA_DIRECTORY + def.getAudioName());
                                    request.setPriority(Priority.HIGH);
                                    request.setNetworkType(NetworkType.ALL);
                                    isFetchDownloading = true;
                                    fetch.enqueue(request,
                                            new Func<Request>() {
                                                @Override
                                                public void call(@NotNull Request result) {
                                                    mAudioProgress.setVisibility(View.VISIBLE);
                                                    isFetchDownloading = true;
                                                }
                                            }
                                            ,
                                            new Func<Error>() {
                                                @Override
                                                public void call(@NotNull Error result) {
                                                    isFetchDownloading = false;
                                                }
                                            }
                                    );
                                }
                            }
                            /////////////////
                            long deckId = currentOutputPlan.getOutputDeckId();
                            long modelId = currentOutputPlan.getOutputModelId();
                            if (mUpdateNoteId == 0) {
                                Long result = mAnkiDroid.getApi().addNote(modelId, deckId, exportFields, mTagEditedByUser);
                                if (result != null) {
                                    Toast.makeText(PopupActivity.this, R.string.str_added, Toast.LENGTH_SHORT).show();
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                        btnAddDefinition.setBackground(ContextCompat.getDrawable(
                                                PopupActivity.this, Utils.getResIdFromAttribute(PopupActivity.this, R.attr.icon_add_done)));
                                    }
                                    clearBigbangSelection();
                                    mNoteEditedByUser = "";
                                    //attach the noteid to the button
                                    btnAddDefinition.setTag(R.id.TAG_NOTE_ID, result);
                                    //if there is a note id field in the model, update the note
                                    int count = 0;
                                    for (String field : currentOutputPlan.getFieldsMap().keySet()) {
                                        if (field.replace(" ", "").toLowerCase().equals("noteid")) {
                                            exportFields[count] = result.toString();
                                            boolean success = mAnkiDroid.getApi().updateNoteFields(
                                                    result.longValue(),
                                                    exportFields
                                            );
                                            if (!success) {
                                                Toast.makeText(PopupActivity.this, R.string.str_error_noteid, Toast.LENGTH_SHORT).show();
                                            }
                                            break;
                                        }
                                        count++;
                                    }
                                    //save note add
                                    HistoryUtil.saveNoteAdd("", getBoldSentence(bigBangLayout.getLines()),
                                            currentDicitonary.getDictionaryName(),
                                            textVeiwDefinition.getText().toString(),
                                            mTranslatedResult,
                                            mNoteEditedByUser,
                                            mTagEditedByUser.toString()
                                    );
                                } else {
                                    Toast.makeText(PopupActivity.this, R.string.str_failed_add, Toast.LENGTH_SHORT).show();
                                }
                            } else {//there's note id, so we need to retrieve note first
                                NoteInfo note = mAnkiDroid.getApi().getNote(mUpdateNoteId);
                                String[] original = note.getFields();
                                Set<String> tags = note.getTags();
                                if (original == null || original.length != exportFields.length) {
                                    Toast.makeText(PopupActivity.this, R.string.str_error_notetype_noncompatible, Toast.LENGTH_SHORT).show();
                                    return;
                                }

                                if (mUpdateAction != null && mUpdateAction.equals("replace")) {
                                    //replace
                                    for (int j = 0; j < original.length; j++) {
                                        if (exportFields[j].isEmpty()) {
                                            exportFields[j] = original[j];
                                        }
                                    }

                                } else {
                                    //append
                                    for (int j = 0; j < original.length; j++) {
                                        if (original[j].trim().isEmpty() || exportFields[j].trim().isEmpty()) {
                                            exportFields[j] = original[j] + exportFields[j];
                                        } else {
                                            exportFields[j] = original[j] + "<br/>" + exportFields[j];
                                        }
                                    }
                                }
                                //we need to check the tag used by user is already in the tags, if not, add it
                                tags.addAll(mTagEditedByUser);
                                boolean success = mAnkiDroid.getApi().updateNoteFields(mUpdateNoteId, exportFields);
                                boolean successTag = mAnkiDroid.getApi().updateNoteTags(mUpdateNoteId, tags);
                                if (success && successTag) {
                                    Toast.makeText(PopupActivity.this, R.string.str_note_updated, Toast.LENGTH_SHORT).show();
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                        btnAddDefinition.setBackground(ContextCompat.getDrawable(
                                                PopupActivity.this, Utils.getResIdFromAttribute(PopupActivity.this, R.attr.icon_add_done)));
                                    }
                                    //btnAddDefinition.setEnabled(false);
                                } else {
                                    Toast.makeText(PopupActivity.this, R.string.str_error_note_update, Toast.LENGTH_SHORT).show();
                                }
                            }
                            if (settings.getAutoCancelPopupQ()) {
                                if (fetch == null) {
                                    finish();
                                } else {
                                    if (!isFetchDownloading) {
                                        finish();
                                    }
                                }
                            }
                        }catch (Exception e){
                            Toast.makeText(PopupActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
        return view;
    }

    private void setupEditNoteDialog() {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(PopupActivity.this);
        LayoutInflater inflater = PopupActivity.this.getLayoutInflater();
        final View dialogView = inflater.inflate(R.layout.dialog_edit_note, null);
        dialogBuilder.setView(dialogView);

        final EditText edt = (EditText) dialogView.findViewById(R.id.edit_note);
        edt.setHorizontallyScrolling(false);
        edt.setMaxLines(4);
        edt.setText(mNoteEditedByUser);
        edt.setSelection(mNoteEditedByUser.length());
        dialogBuilder.setTitle(R.string.dialog_note);
        //dialogBuilder.setMessage("输入笔记");
        dialogBuilder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                mNoteEditedByUser = edt.getText().toString();
            }
        });
//                        dialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
//                            public void onClick(DialogInterface dialog, int whichButton) {
//                                //pass
//                            }
//                        });
        AlertDialog b = dialogBuilder.create();
        b.show();
    }

    private void setupEditTagDialog() {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(PopupActivity.this);
        LayoutInflater inflater = PopupActivity.this.getLayoutInflater();
        final View dialogView = inflater.inflate(R.layout.dialog_edit_tag, null);
        dialogBuilder.setView(dialogView);
        final AutoCompleteTextView editTag = (AutoCompleteTextView) dialogView.findViewById(R.id.edit_tag);
        final CheckBox checkBoxSetAsDefaultTag = (CheckBox) dialogView.findViewById(R.id.checkbox_as_default_tag);
        final ChipGroup tagChipGroup = (ChipGroup) dialogView.findViewById(R.id.tag_chip_list);
        editTag.setImeOptions(EditorInfo.IME_ACTION_DONE);
        if (mTagEditedByUser.size() > 0) {
            String text = Utils.fromTagSetToString(mTagEditedByUser);
            editTag.setText(text);
            editTag.setSelection(text.length());
        }
        tagChipGroup.setSingleSelection(false);
        final List<UserTag> userTags = DataSupport.findAll(UserTag.class);
        for(UserTag userTag : userTags){
            final Chip chip = (Chip) inflater.inflate(R.layout.tag_chip_item, null);
            chip.setText(userTag.getTag());
            chip.setOnCheckedChangeListener(
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                            if(isChecked){
                                mTagEditedByUser.add(chip.getText().toString());
                            }else{
                                mTagEditedByUser.remove(chip.getText().toString());
                            }
                            //tag1,tag2,tag3
                            String text = Utils.fromTagSetToString(mTagEditedByUser);
                            editTag.setText(text);
                            editTag.setSelection(text.length());
                        }
                    }
            );
            if(mTagEditedByUser.contains(chip.getText().toString())){
                chip.setChecked(true);
            }
            tagChipGroup.addView(chip);
        }
//        String[] arr = new String[userTags.size()];
//        for (int i = 0; i < userTags.size(); i++) {
//            arr[i] = userTags.get(i).getTag();
//        }
//        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(PopupActivity.this,
//                R.layout.support_simple_spinner_dropdown_item, arr);
//        editTag.setAdapter(arrayAdapter);
//        editTag.setOnTouchListener(new View.OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                if (editTag.getText().toString().isEmpty()) {
//                    editTag.showDropDown();
//                }
//                return false;
//            }
//        });
        boolean setDefaultQ = settings.getSetAsDefaultTag();
        checkBoxSetAsDefaultTag.setChecked(setDefaultQ);
        dialogBuilder.setTitle(R.string.dialog_tag);
        //dialogBuilder.setMessage("输入笔记");
        dialogBuilder.setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                String tag = editTag.getText().toString().trim();
                if (tag.isEmpty()) {
                    if (checkBoxSetAsDefaultTag.isChecked()) {
                        mTagEditedByUser.clear();
                        Toast.makeText(PopupActivity.this, R.string.tag_cant_be_blank, Toast.LENGTH_LONG).show();
                    } else {
                        settings.setSetAsDefaultTag(false);
                        mTagEditedByUser.clear();
                    }
                    return;
                } else {
                    mTagEditedByUser = Utils.fromStringToTagSet(editTag.getText().toString());
                    settings.setSetAsDefaultTag(checkBoxSetAsDefaultTag.isChecked());
                    settings.setDefaultTag(editTag.getText().toString());
                    for(String t : mTagEditedByUser){
                        if(!userTags.contains(t)){ //add new tag
                            UserTag userTag = new UserTag(t);
                            userTag.save();
                        }
                    }
                }

            }
        });
        AlertDialog b = dialogBuilder.create();
        b.show();
    }

    private void initFetch(){
        FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
                .setDownloadConcurrentLimit(3)
                .build();
        fetch = Fetch.Impl.getInstance(fetchConfiguration);
        fetch.addListener(
                new FetchListener() {
                    @Override
                    public void onAdded(@NotNull Download download) {

                    }

                    @Override
                    public void onQueued(@NotNull Download download, boolean b) {

                    }

                    @Override
                    public void onWaitingNetwork(@NotNull Download download) {

                    }

                    @Override
                    public void onCompleted(@NotNull Download download) {
                        Toast.makeText(PopupActivity.this, "Download Completed!", Toast.LENGTH_SHORT).show();
                        mAudioProgress.setVisibility(View.GONE);
                        isFetchDownloading = false;
                        if(settings.getAutoCancelPopupQ()) {
                            finish();
                        }
                    }

                    @Override
                    public void onError(@NotNull Download download, @NotNull Error error, @Nullable Throwable throwable) {
                        Toast.makeText(PopupActivity.this, "Download Failed!", Toast.LENGTH_SHORT).show();
                        mAudioProgress.setVisibility(View.GONE);
                        isFetchDownloading = false;
                        if(settings.getAutoCancelPopupQ()) {
                            finish();
                        }
                    }

                    @Override
                    public void onDownloadBlockUpdated(@NotNull Download download, @NotNull DownloadBlock downloadBlock, int i) {

                    }

                    @Override
                    public void onStarted(@NotNull Download download, @NotNull List<? extends DownloadBlock> list, int i) {

                    }

                    @Override
                    public void onProgress(@NotNull Download download, long l, long l1) {

                    }

                    @Override
                    public void onPaused(@NotNull Download download) {

                    }

                    @Override
                    public void onResumed(@NotNull Download download) {

                    }

                    @Override
                    public void onCancelled(@NotNull Download download) {

                    }

                    @Override
                    public void onRemoved(@NotNull Download download) {

                    }

                    @Override
                    public void onDeleted(@NotNull Download download) {

                    }
                }
        );
    }

    //cancel auto completetextview focus
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        View v = getCurrentFocus();
        boolean ret = super.dispatchTouchEvent(event);

        if (v instanceof AutoCompleteTextView) {
            View currentFocus = getCurrentFocus();
            int screenCoords[] = new int[2];
            currentFocus.getLocationOnScreen(screenCoords);
            float x = event.getRawX() + currentFocus.getLeft() - screenCoords[0];
            float y = event.getRawY() + currentFocus.getTop() - screenCoords[1];

            if (event.getAction() == MotionEvent.ACTION_UP
                    && (x < currentFocus.getLeft() ||
                    x >= currentFocus.getRight() ||
                    y < currentFocus.getTop() ||
                    y > currentFocus.getBottom())) {
                InputMethodManager imm =
                        (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
                v.clearFocus();
            }
        }
        return ret;
    }



    @Override
    public void onDestroy() {
        super.onDestroy();
        Runtime.getRuntime().gc();
    }

    private void startCBService() {
        Intent intent = new Intent(this, CBWatcherService.class);
        startService(intent);
    }

    private void showProgressBar() {
        progressBar.setVisibility(View.VISIBLE);
        btnSearch.setVisibility(View.GONE);
    }

    private void showSearchButton() {
        progressBar.setVisibility(View.GONE);
        btnSearch.setVisibility(View.VISIBLE);
    }

    private void showPronounce(boolean shouldShow) {
        btnPronounce.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
    }

    private void showTranslateNormal(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mBtnTranslation.setImageResource(Utils.getResIdFromAttribute(this, R.attr.icon_translate_normal));
        }
    }

    private void showTranslateLoading(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mBtnTranslation.setImageResource(Utils.getResIdFromAttribute(this, R.attr.icon_translate_wait));
        }
    }

    private void showTranslateDone(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mBtnTranslation.setImageResource(Utils.getResIdFromAttribute(this, R.attr.icon_translate_done));
        }
    }

    private void showTranslationCardView(boolean show){
        mCardViewTranslation.setVisibility(show ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onSelected(String text) {
        String currentWord = FieldUtil.getSelectedText(bigBangLayout.getLines());
        if (!currentWord.equals(act.getText().toString())) {
            mCurrentKeyWord = currentWord;
            act.setText(currentWord);
            asyncSearch(currentWord);
        }
    }

    @Override
    public void onSearch(String text) {

    }

    @Override
    public void onShare(String text) {

    }

    @Override
    public void onCopy(String text) {

    }

    @Override
    public void onTrans(String text) {

    }

    @Override
    public void onDrag() {

    }

    @Override
    public void onSwitchType(boolean isLocal) {

    }

    @Override
    public void onSwitchSymbol(boolean isShow) {

    }

    @Override
    public void onSwitchSection(boolean isShow) {

    }

    @Override
    public void onDragSelection() {

    }

    @Override
    public void onCancel() {
        act.setText("");
        asyncSearch("");
    }

    void vibarate(int ms) {
        ((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(ms);
    }

    void clearBigbangSelection(){
        for (BigBangLayout.Line line : bigBangLayout.getLines()) {
            List<BigBangLayout.Item> items = line.getItems();
            for (BigBangLayout.Item item : items) {
                if (item.getText().equals(mTargetWord)) {
                    item.setSelected(false);
                }
            }
        }
    }

    private void makeTextViewSelectAndSearch(final TextView textView){
        textView.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // Remove the "copy all" option
                menu.removeItem(android.R.id.cut);
                //menu.removeItem(android.R.id.copy);
                return true;
            }

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // Called when action mode is first created. The menu supplied
                // will be used to generate action buttons for the action mode

                // Here is an example MenuItem
                menu.add(0, 1, 0, "Definition").setIcon(R.drawable.ic_ali_search);
                return true;
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                // Called when an action mode is about to be exited and
                // destroyed
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                    case 1:
                        int min = 0;
                        int max = textView.getText().length();
                        if (textView.isFocused()) {
                            final int selStart = textView.getSelectionStart();
                            final int selEnd = textView.getSelectionEnd();

                            min = Math.max(0, Math.min(selStart, selEnd));
                            max = Math.max(0, Math.max(selStart, selEnd));
                        }
                        // Perform your definition lookup with the selected text
                        final String selectedText = textView.getText().subSequence(min, max).toString();
                        // Finish and close the ActionMode
                        mode.finish();
                        act.setText(selectedText);
                        asyncSearch(selectedText);
                        return true;
                    default:
                        break;
                }
                return false;
            }

        });
    }
}