package cn.leancloud.search;

import androidx.appcompat.app.AppCompatActivity;
import cn.leancloud.AVException;
import cn.leancloud.AVLogger;
import cn.leancloud.AVObject;
import cn.leancloud.callback.FindCallback;
import cn.leancloud.convertor.ObserverBuilder;
import cn.leancloud.utils.LogUtil;
import cn.leancloud.utils.StringUtil;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.alibaba.fastjson.JSON;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class SearchActivity extends AppCompatActivity {
    private static AVLogger LOGGER = LogUtil.getLogger(SearchActivity.class);

    ListView listView;
    LinkedList<AVObject> searchResults = new LinkedList<AVObject>();
    SearchResultAdapter adapter;
    AVSearchQuery searchQuery;
    static final int HIGHLIGHTS_MAX_LENGTH = 200;
    FindCallback<AVObject> searchCallback;
    View loadingView;
    View emtpyResult;
    public static String highlightFontStyle = null;

    public void setSearchQuery(AVSearchQuery query) {
        this.searchQuery = query;
    }

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

        setContentView(Resources.layout.search_activity(this));
        setupActionBar();
        listView = (ListView) findViewById(Resources.id.search_result_listview(this));
        loadingView =
            LayoutInflater.from(this).inflate(Resources.layout.search_loading(this), null);
        emtpyResult = findViewById(Resources.id.search_emtpy_result(this));
        listView.addFooterView(loadingView);
        loadingView.setVisibility(View.INVISIBLE);
        if (this.getIntent().getExtras() != null) {
            String searchString =
                getIntent().getExtras().getString(AVSearchQuery.DATA_EXTRA_SEARCH_KEY);
            searchQuery = JSON.parseObject(searchString, AVSearchQuery.class);
        }
        if (null != searchQuery) {
            searchCallback = new FindCallback<AVObject>() {

                @Override
                public void done(List<AVObject> avObjects, AVException avException) {
                    if (avException == null) {
                        searchResults.addAll(avObjects);
                        if (adapter == null) {
                            adapter = new SearchResultAdapter();
                            listView.setAdapter(adapter);
                            listView.setOnScrollListener(adapter);
                        } else {
                            adapter.notifyDataSetChanged();
                            hideLoadingView();
                        }
                        if (searchResults.size() == 0) {
                            emtpyResult.setVisibility(View.VISIBLE);
                            listView.setVisibility(View.GONE);
                        } else {
                            emtpyResult.setVisibility(View.GONE);
                            listView.setVisibility(View.VISIBLE);
                        }

                    }
                }
            };
            searchQuery.findInBackground().subscribe(ObserverBuilder.buildSingleObserver(searchCallback));
        }
    }

    @SuppressLint("NewApi")
    private void setupActionBar() {
        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.setCustomView(Resources.layout.search_actionbar(this));
            actionBar.setDisplayShowCustomEnabled(true);
            actionBar.setDisplayShowHomeEnabled(false);
            actionBar.setDisplayShowTitleEnabled(false);
            View backButton =
                actionBar.getCustomView()
                    .findViewById(Resources.id.search_actionbar_back(this));
            backButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onBackPressed();
                    finish();
                }
            });
        }
    }

    public void showLoadingView() {
        if (loadingView != null) {
            loadingView.setVisibility(View.VISIBLE);
        }

    }

    public void hideLoadingView() {
        if (loadingView != null) {
            loadingView.setVisibility(View.INVISIBLE);
        }
    }

    public static String highlightStringMerge(Map<String, List<String>> highlights) {
        if (highlights != null) {
            StringBuilder sb = new StringBuilder();
            for (String key : highlights.keySet()) {
                sb.append(StringUtil.join("...", highlights.get(key)));
            }
            if (sb.length() > HIGHLIGHTS_MAX_LENGTH) {
                String tempString = sb.substring(0, HIGHLIGHTS_MAX_LENGTH);
                StringBuilder tempSB = new StringBuilder(tempString).reverse();
                int lastHeadTagIndex = tempSB.indexOf("<me>");
                int lastTailTagIndex = tempSB.indexOf("<me/>");
                if (lastHeadTagIndex < lastTailTagIndex) {
                    return highLightStringStyle(tempSB.reverse().substring(0,
                        HIGHLIGHTS_MAX_LENGTH - lastTailTagIndex));
                }
                return highLightStringStyle(tempString);
            }
            return highLightStringStyle(sb.toString());

        } else {
            return "";
        }
    }

    public static String highLightStringStyle(String string) {
        string =
            string.replaceAll("<em>", StringUtil.isEmpty(highlightFontStyle)
                ? "<font color='#E68A00'>"
                : highlightFontStyle);
        string = string.replaceAll("</em>", "</font>");
        return string;
    }

    /**
     * 您可以通过设定类似html font style来设定匹配高亮的风格
     *
     * @param style
     */
    public static void setHighLightStyle(String style) {
        highlightFontStyle = style;
    }

    public class ViewHolder {
        TextView title;
        TextView description;
        TextView openApp;
    }

    public class SearchResultAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
        Context mContext = SearchActivity.this;
        int lastVisibleItemId;
        volatile boolean loading;

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

        @Override
        public Object getItem(int position) {
            return searchResults.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {


            final AVObject item = (AVObject) getItem(position);
            ViewHolder holder = null;
            if (convertView == null) {
                convertView =
                    LayoutInflater.from(SearchActivity.this).inflate(
                        Resources.layout.search_result_item(mContext), null);
                holder = new ViewHolder();
                holder.title =
                    (TextView) convertView.findViewById(Resources.id
                        .search_result_title(mContext));
                holder.description =
                    (TextView) convertView.findViewById(Resources.id
                        .search_result_description(mContext));
                holder.openApp =
                    (TextView) convertView.findViewById(Resources.id
                        .search_result_open_app(mContext));
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            if (!StringUtil.isEmpty(searchQuery.getTitleAttribute())) {
                holder.title.setText(Html.fromHtml(item.get(searchQuery.getTitleAttribute()).toString()));
                holder.description.setVisibility(View.VISIBLE);
                holder.description.setText(Html
                    .fromHtml(highlightStringMerge((Map<String, List<String>>) item
                        .get(AVSearchQuery.AVSEARCH_HIGHTLIGHT))));
            } else {
                holder.title.setText(Html.fromHtml(highlightStringMerge((Map<String, List<String>>) item
                    .get(AVSearchQuery.AVSEARCH_HIGHTLIGHT))));
                holder.description.setVisibility(View.GONE);
            }
            if (!StringUtil.isEmpty(item.getString(AVSearchQuery.AVSEARCH_APP_URL))) {
                holder.openApp.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        Intent i = new Intent(Intent.ACTION_VIEW);
                        String link =
                            StringUtil.isEmpty(item.getString(AVSearchQuery.AVSEARCH_DEEP_LINK)) ? item
                                .getString(AVSearchQuery.AVSEARCH_APP_URL) : item
                                .getString(AVSearchQuery.AVSEARCH_DEEP_LINK);
                        i.setData(Uri.parse(link));
                        startActivity(i);
                    }
                });
            }

            return convertView;
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                             int totalItemCount) {
            lastVisibleItemId = firstVisibleItem + visibleItemCount;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

            if (lastVisibleItemId >= searchResults.size()
                && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                showLoadingView();
                if (null != searchQuery) {
                    searchQuery.findInBackground().subscribe(ObserverBuilder.buildSingleObserver(searchCallback));
                }
            } else {
                hideLoadingView();
            }
        }
    }
}