/*
* Copyright (C) 2014 Fastboot Mobile, LLC.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, see <http://www.gnu.org/licenses>.
*/
package com.fastbootmobile.encore.app.fragments;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v7.graphics.Palette;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.fastbootmobile.encore.app.AlbumActivity;
import com.fastbootmobile.encore.app.ArtistActivity;
import com.fastbootmobile.encore.app.PlaylistActivity;
import com.fastbootmobile.encore.app.R;
import com.fastbootmobile.encore.app.adapters.SearchAdapter;
import com.fastbootmobile.encore.app.ui.MaterialTransitionDrawable;
import com.fastbootmobile.encore.framework.PlaybackProxy;
import com.fastbootmobile.encore.model.Album;
import com.fastbootmobile.encore.model.Artist;
import com.fastbootmobile.encore.model.Playlist;
import com.fastbootmobile.encore.model.SearchResult;
import com.fastbootmobile.encore.model.Song;
import com.fastbootmobile.encore.providers.ILocalCallback;
import com.fastbootmobile.encore.providers.IMusicProvider;
import com.fastbootmobile.encore.providers.ProviderAggregator;
import com.fastbootmobile.encore.utils.Utils;
import java.lang.ref.WeakReference;
import java.util.List;
/**
* Fragment displaying search results
*/
public class SearchFragment extends Fragment implements ILocalCallback {
private static final String TAG = "SearchFragment";
private static final int MSG_UPDATE_RESULTS = 1;
private static final int MSG_DATASET_CHANGED = 2;
public static final String KEY_SPECIAL_MORE = "__encore_plus";
private SearchAdapter mAdapter;
private Handler mHandler;
private List<SearchResult> mSearchResults;
private String mQuery;
private ProgressBar mLoadingBar;
private int mNumProvidersResponse;
private static class SearchHandler extends Handler {
private WeakReference<SearchFragment> mParent;
public SearchHandler(WeakReference<SearchFragment> parent) {
mParent = parent;
}
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_UPDATE_RESULTS) {
mParent.get().updateSearchResults();
} else if (msg.what == MSG_DATASET_CHANGED) {
mParent.get().mAdapter.notifyDataSetChanged();
}
}
}
/**
* Default constructor
*/
public SearchFragment() {
mHandler = new SearchHandler(new WeakReference<>(this));
setRetainInstance(true);
}
public void setArguments(String query) {
mQuery = query;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View root = inflater.inflate(R.layout.fragment_search, container, false);
assert root != null;
mLoadingBar = (ProgressBar) root.findViewById(R.id.pbLoading);
mAdapter = new SearchAdapter();
ExpandableListView listView = (ExpandableListView) root.findViewById(R.id.expandablelv_search);
listView.setAdapter(mAdapter);
listView.setGroupIndicator(null);
for (int i = 0; i < 4; i++) {
listView.expandGroup(i, false);
}
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView expandableListView, View view, int i, int i2, long l) {
if (mSearchResults != null) {
switch (i) {
case SearchAdapter.ARTIST:
onArtistClick(i2, view);
break;
case SearchAdapter.ALBUM:
onAlbumClick(i2, view);
break;
case SearchAdapter.SONG:
onSongClick(i2);
break;
case SearchAdapter.PLAYLIST:
onPlaylistClick(i2, view);
break;
default:
Log.e(TAG, "Unknown child group id " + i);
break;
}
return true;
} else {
return false;
}
}
});
// Restore previous search results, in case we're rotating
if (mSearchResults != null) {
mAdapter.appendResults(mSearchResults);
mAdapter.notifyDataSetChanged();
}
return root;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
ProviderAggregator.getDefault().addUpdateCallback(this);
}
@Override
public void onDetach() {
super.onDetach();
ProviderAggregator.getDefault().removeUpdateCallback(this);
}
public void resetResults() {
if (mAdapter != null) {
mAdapter.clear();
}
}
private void onSongClick(int i) {
SearchAdapter.SearchEntry entry = mAdapter.getChild(SearchAdapter.SONG, i);
if (entry.ref.equals(KEY_SPECIAL_MORE)) {
mAdapter.setGroupMaxCount(SearchAdapter.SONG,
mAdapter.getGroupMaxCount(SearchAdapter.SONG) + 5);
} else {
final ProviderAggregator aggregator = ProviderAggregator.getDefault();
Song song = aggregator.retrieveSong(entry.ref, entry.identifier);
if (song != null) {
PlaybackProxy.playSong(song);
}
}
}
private void onAlbumClick(int i, View v) {
if (mAdapter.getChildrenCount(SearchAdapter.ALBUM) > 1) {
SearchAdapter.SearchEntry entry = mAdapter.getChild(SearchAdapter.ALBUM, i);
if (entry.ref.equals(KEY_SPECIAL_MORE)) {
mAdapter.setGroupMaxCount(SearchAdapter.ALBUM,
mAdapter.getGroupMaxCount(SearchAdapter.ALBUM) + 5);
} else {
SearchAdapter.ViewHolder holder = (SearchAdapter.ViewHolder) v.getTag();
Bitmap hero = ((MaterialTransitionDrawable) holder.albumArtImageView.getDrawable()).getFinalDrawable().getBitmap();
int color = 0xffffff;
if (hero != null) {
Palette palette = Palette.generate(hero);
Palette.Swatch darkVibrantColor = palette.getDarkVibrantSwatch();
Palette.Swatch darkMutedColor = palette.getDarkMutedSwatch();
if (darkVibrantColor != null) {
color = darkVibrantColor.getRgb();
} else if (darkMutedColor != null) {
color = darkMutedColor.getRgb();
} else {
color = getResources().getColor(R.color.default_album_art_background);
}
}
Intent intent = AlbumActivity.craftIntent(getActivity(), hero, entry.ref,
entry.identifier, color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ImageView ivCover = holder.albumArtImageView;
ActivityOptions opt = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
new Pair<View, String>(ivCover, "itemImage"));
getActivity().startActivity(intent, opt.toBundle());
} else {
startActivity(intent);
}
}
}
}
private void onArtistClick(int i, View v) {
if (mAdapter.getChildrenCount(SearchAdapter.ARTIST) > 1) {
SearchAdapter.SearchEntry entry = mAdapter.getChild(SearchAdapter.ARTIST, i);
if (entry.ref.equals(KEY_SPECIAL_MORE)) {
mAdapter.setGroupMaxCount(SearchAdapter.ARTIST,
mAdapter.getGroupMaxCount(SearchAdapter.ARTIST) + 5);
} else {
SearchAdapter.ViewHolder holder = (SearchAdapter.ViewHolder) v.getTag();
ImageView ivCover = holder.albumArtImageView;
Bitmap hero = ((MaterialTransitionDrawable) ivCover.getDrawable()).getFinalDrawable().getBitmap();
int color = 0xffffff;
if (hero != null) {
Palette palette = Palette.generate(hero);
Palette.Swatch darkVibrantColor = palette.getDarkVibrantSwatch();
Palette.Swatch darkMutedColor = palette.getDarkMutedSwatch();
if (darkVibrantColor != null) {
color = darkVibrantColor.getRgb();
} else if (darkMutedColor != null) {
color = darkMutedColor.getRgb();
} else {
color = getResources().getColor(R.color.default_album_art_background);
}
}
Intent intent = new Intent(getActivity(), ArtistActivity.class);
intent.putExtra(ArtistActivity.EXTRA_ARTIST, entry.ref);
intent.putExtra(ArtistActivity.EXTRA_BACKGROUND_COLOR,
color);
Utils.queueBitmap(ArtistActivity.BITMAP_ARTIST_HERO, hero);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ActivityOptions opt = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
ivCover, "itemImage");
getActivity().startActivity(intent, opt.toBundle());
} else {
startActivity(intent);
}
}
}
}
private void onPlaylistClick(int i, View v) {
if (mAdapter.getChildrenCount(SearchAdapter.PLAYLIST) > 1) {
final ProviderAggregator aggregator = ProviderAggregator.getDefault();
final SearchAdapter.SearchEntry entry = mAdapter.getChild(SearchAdapter.PLAYLIST, i);
if (entry.ref.equals(KEY_SPECIAL_MORE)) {
mAdapter.setGroupMaxCount(SearchAdapter.PLAYLIST,
mAdapter.getGroupMaxCount(SearchAdapter.PLAYLIST) + 5);
} else {
Playlist playlist = aggregator.retrievePlaylist(entry.ref, entry.identifier);
if (playlist != null) {
Intent intent = PlaylistActivity.craftIntent(getActivity(), playlist,
((BitmapDrawable) getResources().getDrawable(R.drawable.album_placeholder)).getBitmap());
startActivity(intent);
}
}
}
}
@Override
public void onSongUpdate(List<Song> s) {
if (mAdapter == null) {
return;
}
for (Song song : s) {
if (mAdapter.contains(song)) {
mHandler.removeMessages(MSG_DATASET_CHANGED);
mHandler.sendEmptyMessage(MSG_DATASET_CHANGED);
return;
}
}
}
@Override
public void onAlbumUpdate(List<Album> a) {
if (mAdapter == null) {
return;
}
for (Album album : a) {
if (mAdapter.contains(album)) {
mHandler.removeMessages(MSG_DATASET_CHANGED);
mHandler.sendEmptyMessage(MSG_DATASET_CHANGED);
return;
}
}
}
@Override
public void onPlaylistUpdate(List<Playlist> p) {
if (mAdapter == null) {
return;
}
for (Playlist playlist : p) {
if (mAdapter.contains(playlist)) {
mHandler.removeMessages(MSG_DATASET_CHANGED);
mHandler.sendEmptyMessage(MSG_DATASET_CHANGED);
return;
}
}
}
@Override
public void onPlaylistRemoved(String ref) {
}
@Override
public void onArtistUpdate(List<Artist> a) {
if (mAdapter == null) {
return;
}
for (Artist artist : a) {
if (mAdapter.contains(artist)) {
mHandler.removeMessages(MSG_DATASET_CHANGED);
mHandler.sendEmptyMessage(MSG_DATASET_CHANGED);
return;
}
}
}
@Override
public void onProviderConnected(IMusicProvider provider) {
}
@Override
public void onSearchResult(final List<SearchResult> searchResults) {
for (SearchResult searchResult : searchResults) {
if (searchResult.getQuery().equals(mQuery)) {
mSearchResults = searchResults;
mHandler.sendEmptyMessage(MSG_UPDATE_RESULTS);
mNumProvidersResponse++;
break;
}
}
}
private void updateSearchResults() {
final Activity act = getActivity();
if (act != null) {
getActivity().setTitle("'" + mSearchResults.get(0).getQuery() + "'");
getActivity().setProgressBarIndeterminateVisibility(false);
if (mNumProvidersResponse >= 2) {
mLoadingBar.setVisibility(View.GONE);
}
} else {
mHandler.sendEmptyMessage(MSG_UPDATE_RESULTS);
}
if (mAdapter != null) {
mAdapter.appendResults(mSearchResults);
mAdapter.notifyDataSetChanged();
}
}
}