package io.github.xwz.base.fragments;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.VerticalGridView;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.github.xwz.base.R;
import io.github.xwz.base.Utils;
import io.github.xwz.base.adapters.CardSelector;
import io.github.xwz.base.api.EpisodeBaseModel;
import io.github.xwz.base.api.PlayHistory;
import io.github.xwz.base.content.ContentManagerBase;
import io.github.xwz.base.views.EpisodeDetailsView;
public abstract class DetailsFragment extends android.support.v17.leanback.app.RowsFragment {
private static final String TAG = "DetailsFragment";
private EpisodeDetailsView mDetailView;
private int mHeaderHeight;
private EpisodeBaseModel mCurrentEpisode;
private EpisodeBaseModel mLoadedEpisode;
private ArrayObjectAdapter otherEpisodes;
private boolean loadedOtherEpisodes = false;
private List<String> mOtherEpisodeUrls = new ArrayList<>();
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "Action: " + action + ", tag: " + intent.getStringExtra(ContentManagerBase.CONTENT_TAG));
if (ContentManagerBase.CONTENT_EPISODE_DONE.equals(action)) {
updateEpisodeData(intent);
}
if (ContentManagerBase.CONTENT_EPISODE_ERROR.equals(action)) {
Utils.showToast(getActivity(), "Unable to find episode details.");
}
}
};
protected List<String> getOtherEpisodeUrls() {
return mOtherEpisodeUrls;
}
protected abstract ContentManagerBase getContentManger();
protected EpisodeBaseModel getCurrentEpisode() {
return mCurrentEpisode;
}
protected EpisodeDetailsView getDetailView() {
return mDetailView;
}
protected void setCurrentEpisode(EpisodeBaseModel ep) {
mCurrentEpisode = ep;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EpisodeBaseModel episode = (EpisodeBaseModel) getActivity().getIntent().getSerializableExtra(ContentManagerBase.CONTENT_ID);
if (episode == null) {
episode = getEpisodeFromGlobalSearchIntent();
}
if (episode != null) {
setupEpisode(episode);
} else {
Log.e(TAG, "No episode set.");
}
}
private void setupEpisode(EpisodeBaseModel episode) {
mLoadedEpisode = episode;
selectCurrentEpisode(episode, true);
Point size = Utils.getDisplaySize(getActivity());
mHeaderHeight = Math.round(size.y * 0.475f);
setupAdapter(episode);
setupListeners();
}
private EpisodeBaseModel getEpisodeFromGlobalSearchIntent() {
Intent intent = getActivity().getIntent();
String action = intent.getAction();
if (ContentManagerBase.GLOBAL_SEARCH_INTENT.equals(action)) {
Log.d(TAG, "getEpisodeFromGlobalSearchIntent");
Bundle data = intent.getExtras();
if (data != null) {
String href = data.getString(ContentManagerBase.KEY_EXTRA_NAME);
Log.d(TAG, "Search result: " + href);
return getContentManger().getEpisode(href);
}
Log.w(TAG, "Unable to find href from search result");
}
return null;
}
private void setupListeners() {
setOnItemViewClickedListener(getItemClickedListener());
setOnItemViewSelectedListener(getItemSelectedListener());
}
private void setupAdapter(EpisodeBaseModel episode) {
ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ListRowPresenter());
otherEpisodes = new ArrayObjectAdapter(new CardSelector());
otherEpisodes.add(0, episode);
adapter.add(new ListRow(new HeaderItem(0, null), otherEpisodes));
setAdapter(adapter);
}
protected void selectCurrentEpisode(EpisodeBaseModel episode, boolean initial) {
Log.d(TAG, "Showing details: " + episode);
if (!episode.equals(mCurrentEpisode)) {
mCurrentEpisode = episode;
getContentManger().fetchEpisode(episode);
if (mDetailView != null) {
mDetailView.setEpisode(episode);
}
}
}
private void updateEpisodeData(Intent intent) {
String href = intent.getStringExtra(ContentManagerBase.CONTENT_TAG);
EpisodeBaseModel ep = getContentManger().getEpisode(href);
if (ep != null) {
if (ep.equals(mCurrentEpisode)) {
mCurrentEpisode.merge(ep);
mDetailView.updateEpisode(mCurrentEpisode);
}
if (ep.equals(mLoadedEpisode) && !loadedOtherEpisodes) {
updateRelatedEpisodes(ep.getOtherEpisodes());
loadedOtherEpisodes = true;
mOtherEpisodeUrls = mLoadedEpisode.getOtherEpisodeUrls(ContentManagerBase.OTHER_EPISODES);
Log.d(TAG, "Other episodes:" + mOtherEpisodeUrls);
}
}
}
private void updateRelatedEpisodes(Map<String, List<EpisodeBaseModel>> others) {
boolean updated = false;
ArrayObjectAdapter adapter = (ArrayObjectAdapter) getAdapter();
for (Map.Entry<String, List<EpisodeBaseModel>> list : others.entrySet()) {
String title = list.getKey();
Log.d(TAG, "More: " + title);
if (ContentManagerBase.OTHER_EPISODES.equals(title)) {
otherEpisodes.addAll(otherEpisodes.size(), list.getValue());
} else {
ArrayObjectAdapter more = new ArrayObjectAdapter(new CardSelector());
more.addAll(0, list.getValue());
adapter.add(new ListRow(new HeaderItem(0, title), more));
}
updated = true;
}
if (updated) {
adapter.notifyArrayItemRangeChanged(0, adapter.size());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
if (view instanceof FrameLayout) {
insertHeader(inflater, (FrameLayout) view);
}
return view;
}
private void insertHeader(LayoutInflater inflater, FrameLayout container) {
VerticalGridView grid = findFirstGrid(container);
if (grid != null) {
View header = inflater.inflate(R.layout.episode_details_view, container, false);
View bottom = inflater.inflate(R.layout.dark_gradient, container, false);
container.addView(header, 0);
container.addView(bottom, 1);
setupGridAlignment(grid);
setupHeaderView(grid, header);
setupGradient(bottom);
} else {
Utils.showToast(getActivity(), "No Grid Found!");
}
}
private void setupGradient(View bottom) {
int height = getResources().getDimensionPixelSize(R.dimen.episode_detail_padding_bottom);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) bottom.getLayoutParams();
lp.topMargin = mHeaderHeight;
lp.height = height;
bottom.setLayoutParams(lp);
}
private void setupHeaderView(VerticalGridView grid, View header) {
mDetailView = new EpisodeDetailsView(getActivity(), header);
if (mCurrentEpisode != null) {
mDetailView.setEpisode(mCurrentEpisode);
}
int height = getResources().getDimensionPixelSize(R.dimen.episode_detail_padding_bottom);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) header.getLayoutParams();
lp.height = mHeaderHeight + height;
header.setLayoutParams(lp);
}
private void setupGridAlignment(VerticalGridView grid) {
int cardHeight = getResources().getDimensionPixelSize(R.dimen.card_height);
int titleHeight = getResources().getDimensionPixelSize(R.dimen.lb_browse_header_height);
grid.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_LOW_EDGE);
grid.setWindowAlignmentOffset(cardHeight + titleHeight);
grid.setWindowAlignmentOffsetPercent(VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) grid.getLayoutParams();
lp.topMargin = mHeaderHeight;
grid.setLayoutParams(lp);
}
private VerticalGridView findFirstGrid(ViewGroup container) {
for (int i = 0, k = container.getChildCount(); i < k; i++) {
View view = container.getChildAt(i);
if (view instanceof VerticalGridView) {
return (VerticalGridView) view;
}
}
return null;
}
protected abstract Class<?> getPlayerActivityClass();
private OnItemViewClickedListener getItemClickedListener() {
return new OnItemViewClickedListener() {
@Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
Log.d(TAG, "Clicked item:" + item);
if (item instanceof EpisodeBaseModel) {
EpisodeBaseModel ep = (EpisodeBaseModel) item;
Intent intent = new Intent(getActivity(), getPlayerActivityClass());
intent.putExtra(ContentManagerBase.CONTENT_ID, ep);
String[] others = getOtherEpisodeUrls().toArray(new String[getOtherEpisodeUrls().size()]);
intent.putExtra(ContentManagerBase.OTHER_EPISODES, others);
startActivity(intent);
}
}
};
}
private OnItemViewSelectedListener getItemSelectedListener() {
return new OnItemViewSelectedListener() {
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
Log.d(TAG, "Selected item:" + item);
if (item instanceof EpisodeBaseModel) {
selectCurrentEpisode((EpisodeBaseModel) item, false);
}
}
};
}
@Override
public void onResume() {
super.onResume();
registerReceiver();
}
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
}
private void registerReceiver() {
Log.i(TAG, "Register receiver");
IntentFilter filter = new IntentFilter();
filter.addAction(ContentManagerBase.CONTENT_EPISODE_START);
filter.addAction(ContentManagerBase.CONTENT_EPISODE_DONE);
filter.addAction(ContentManagerBase.CONTENT_EPISODE_ERROR);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, filter);
}
}