/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.car.carlauncher;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * The search result adapter that binds the filtered result to a list view.
 */

final class SearchResultAdapter
        extends RecyclerView.Adapter<SearchResultAdapter.ViewHolder> implements Filterable {
    private final Activity mContext;
    private List<AppMetaData> mAllApps;
    private List<AppMetaData> mSearchResults;
    private AppSearchFilter filter;
    private boolean mIsDistractionOptimizationRequired;

    public SearchResultAdapter(Activity context) {
        mContext = context;
        mSearchResults = null;
    }

    public void setIsDistractionOptimizationRequired(boolean isDistractionOptimizationRequired) {
        mIsDistractionOptimizationRequired = isDistractionOptimizationRequired;
        notifyDataSetChanged();
    }

    public void setAllApps(List<AppMetaData> apps) {
        mAllApps = apps;
        notifyDataSetChanged();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private View mAppItem;
        private ImageView mAppIconView;
        private TextView mAppNameView;

        public ViewHolder(View view) {
            super(view);
            mAppItem = view.findViewById(R.id.app_item);
            mAppIconView = mAppItem.findViewById(R.id.app_icon);
            mAppNameView = mAppItem.findViewById(R.id.app_name);
        }

        public void bind(AppMetaData app, View.OnClickListener listener) {
            if (app == null) {
                // Empty out the view
                mAppIconView.setImageDrawable(null);
                mAppNameView.setText(null);
                mAppItem.setClickable(false);
                mAppItem.setOnClickListener(null);
            } else {
                mAppIconView.setImageDrawable(app.getIcon());
                mAppNameView.setText(app.getDisplayName());
                mAppItem.setClickable(true);
                mAppItem.setOnClickListener(listener);
            }
        }
    }

    /**
     * This filter does a simple case insensitive text match based on the application
     * display name. e.g. "gm" -> "gmail".
     * It only matches apps starting with the search query. It does not do sub-string matching.
     */
    private class AppSearchFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if (constraint != null && constraint.length() > 0) {
                List filterList = new ArrayList();
                for (int i = 0; i < mAllApps.size(); i++) {
                    AppMetaData app = mAllApps.get(i);
                    if (shouldShowApp(
                            app.getDisplayName(),
                            constraint.toString(),
                            app.getIsDistractionOptimized())) {
                        filterList.add(app);
                    }
                }
                Collections.sort(filterList, AppLauncherUtils.ALPHABETICAL_COMPARATOR);
                results.count = filterList.size();
                results.values = filterList;
            } else {
                results.count = 0;
                results.values = null;
            }

            return results;
        }

        private boolean shouldShowApp(
                String displayName, String constraint, boolean isDistractionOptimized) {
            if (!mIsDistractionOptimizationRequired
                    || (mIsDistractionOptimizationRequired && isDistractionOptimized)) {
                Pattern pattern = Pattern.compile(
                        "^" + constraint + ".*$", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
                return pattern.matcher(displayName).matches();
            }
            return false;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mSearchResults = (ArrayList) results.values;
            notifyDataSetChanged();
        }
    }

    @Override
    public Filter getFilter() {
        if (filter == null) {
            filter = new AppSearchFilter();
        }
        return filter;
    }

    @NonNull
    @Override
    public SearchResultAdapter.ViewHolder onCreateViewHolder(
            @NonNull ViewGroup parent, int viewType) {
        View view = mContext.getLayoutInflater().inflate(R.layout.app_search_result_item, null);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull SearchResultAdapter.ViewHolder holder, int position) {
        // Get the data item for this position
        AppMetaData app = mSearchResults.get(position);
        holder.bind(app, v -> AppLauncherUtils.launchApp(mContext, app));
    }

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

    @Override
    public int getItemCount() {
        if (mSearchResults != null) {
            return mSearchResults.size();
        } else {
            return 0;
        }
    }

    void clearResults() {
        mSearchResults.clear();
        notifyDataSetChanged();
    }
}
