/*
 * Copyright (C) 2015 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.tv.search;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.leanback.app.SearchFragment;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.HeaderItem;
import androidx.leanback.widget.ImageCardView;
import androidx.leanback.widget.ListRow;
import androidx.leanback.widget.ListRowPresenter;
import androidx.leanback.widget.ObjectAdapter;
import androidx.leanback.widget.OnItemViewClickedListener;
import androidx.leanback.widget.Presenter;
import androidx.leanback.widget.Row;
import androidx.leanback.widget.RowPresenter;
import androidx.leanback.widget.SearchBar;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.tv.MainActivity;
import com.android.tv.R;
import com.android.tv.common.util.PermissionUtils;
import com.android.tv.util.images.ImageLoader;
import java.util.List;

public class ProgramGuideSearchFragment extends SearchFragment {
    private static final String TAG = "ProgramGuideSearch";
    private static final boolean DEBUG = false;
    private static final int SEARCH_RESULT_MAX = 10;

    private final Presenter mPresenter =
            new Presenter() {
                @Override
                public Presenter.ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
                    if (DEBUG) Log.d(TAG, "onCreateViewHolder");

                    ImageCardView cardView = new ImageCardView(mMainActivity);
                    cardView.setFocusable(true);
                    cardView.setFocusableInTouchMode(true);
                    cardView.setMainImageAdjustViewBounds(false);

                    Resources res = mMainActivity.getResources();
                    cardView.setMainImageDimensions(
                            res.getDimensionPixelSize(R.dimen.card_image_layout_width),
                            res.getDimensionPixelSize(R.dimen.card_image_layout_height));

                    return new Presenter.ViewHolder(cardView);
                }

                @Override
                public void onBindViewHolder(ViewHolder viewHolder, Object o) {
                    ImageCardView cardView = (ImageCardView) viewHolder.view;
                    LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
                    if (DEBUG) Log.d(TAG, "onBindViewHolder result:" + result);

                    cardView.setTitleText(result.getTitle());
                    if (!TextUtils.isEmpty(result.getImageUri())) {
                        ImageLoader.loadBitmap(
                                mMainActivity,
                                result.getImageUri(),
                                mMainCardWidth,
                                mMainCardHeight,
                                createImageLoaderCallback(cardView));
                    } else {
                        cardView.setMainImage(
                                mMainActivity.getDrawable(R.drawable.ic_tv_app_96x96));
                    }
                }

                @Override
                public void onUnbindViewHolder(ViewHolder viewHolder) {
                    // Do nothing here.
                }
            };

    private static ImageLoader.ImageLoaderCallback<ImageCardView> createImageLoaderCallback(
            ImageCardView cardView) {
        return new ImageLoader.ImageLoaderCallback<ImageCardView>(cardView) {
            @Override
            public void onBitmapLoaded(ImageCardView cardView, Bitmap bitmap) {
                cardView.setMainImage(
                        new BitmapDrawable(cardView.getContext().getResources(), bitmap));
            }
        };
    }

    private final SearchResultProvider mSearchResultProvider =
            new SearchResultProvider() {
                @Override
                public ObjectAdapter getResultsAdapter() {
                    return mResultAdapter;
                }

                @Override
                public boolean onQueryTextChange(String query) {
                    searchAndRefresh(query);
                    return true;
                }

                @Override
                public boolean onQueryTextSubmit(String query) {
                    searchAndRefresh(query);
                    return true;
                }
            };

    private final OnItemViewClickedListener mItemClickedListener =
            new OnItemViewClickedListener() {
                @Override
                public void onItemClicked(
                        Presenter.ViewHolder viewHolder,
                        Object o,
                        RowPresenter.ViewHolder viewHolder1,
                        Row row) {
                    LocalSearchProvider.SearchResult result = (LocalSearchProvider.SearchResult) o;
                    mMainActivity.getFragmentManager().popBackStack();
                    mMainActivity.tuneToChannel(
                            mMainActivity
                                    .getChannelDataManager()
                                    .getChannel(result.getChannelId()));
                }
            };

    private final ArrayObjectAdapter mResultAdapter =
            new ArrayObjectAdapter(new ListRowPresenter());
    private MainActivity mMainActivity;
    private SearchInterface mSearch;
    private int mMainCardWidth;
    private int mMainCardHeight;
    private SearchTask mSearchTask;

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

        mMainActivity = (MainActivity) getActivity();
        if (PermissionUtils.hasAccessAllEpg(mMainActivity)) {
            mSearch = new TvProviderSearch(mMainActivity);
        } else {
            mSearch = new DataManagerSearch(mMainActivity);
        }
        Resources res = getResources();
        mMainCardWidth = res.getDimensionPixelSize(R.dimen.card_image_layout_width);
        mMainCardHeight = res.getDimensionPixelSize(R.dimen.card_image_layout_height);
    }

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = super.onCreateView(inflater, container, savedInstanceState);
        v.setBackgroundResource(R.color.program_guide_scrim);

        setBadgeDrawable(mMainActivity.getDrawable(R.drawable.ic_tv_app_96x96));
        setSearchResultProvider(mSearchResultProvider);
        setOnItemViewClickedListener(mItemClickedListener);
        return v;
    }

    @Override
    public void onResume() {
        super.onResume();

        SearchBar searchBar = (SearchBar) getView().findViewById(R.id.lb_search_bar);
        searchBar.setSearchQuery("");
        mResultAdapter.clear();
    }

    private void searchAndRefresh(String query) {
        // TODO: Search directly from program data manager for performance.
        // TODO: Search upcoming programs.
        if (mSearchTask != null) {
            mSearchTask.cancel(true);
        }
        mSearchTask = new SearchTask(query);
        mSearchTask.execute();
    }

    private class SearchTask extends AsyncTask<Void, Void, List<LocalSearchProvider.SearchResult>> {
        private final String mQuery;

        public SearchTask(String query) {
            mQuery = query;
        }

        @Override
        protected List<LocalSearchProvider.SearchResult> doInBackground(Void... params) {
            return mSearch.search(
                    mQuery, SEARCH_RESULT_MAX, TvProviderSearch.ACTION_TYPE_AMBIGUOUS);
        }

        @Override
        protected void onPostExecute(List<LocalSearchProvider.SearchResult> results) {
            super.onPostExecute(results);
            mResultAdapter.clear();

            if (DEBUG) {
                Log.d(
                        TAG,
                        "searchAndRefresh query="
                                + mQuery
                                + " results="
                                + ((results == null) ? 0 : results.size()));
            }

            if (results == null || results.size() == 0) {
                HeaderItem header =
                        new HeaderItem(
                                0, mMainActivity.getString(R.string.search_result_no_result));
                ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
                mResultAdapter.add(new ListRow(header, resultsAdapter));
            } else {
                HeaderItem header =
                        new HeaderItem(0, mMainActivity.getString(R.string.search_result_title));
                ArrayObjectAdapter resultsAdapter = new ArrayObjectAdapter(mPresenter);
                resultsAdapter.addAll(0, results);
                mResultAdapter.add(new ListRow(header, resultsAdapter));
            }
            mSearchTask = null;
        }
    }
}
