package com.ronakmanglani.watchlist.ui.fragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.ronakmanglani.watchlist.R;
import com.ronakmanglani.watchlist.WatchlistApp;
import com.ronakmanglani.watchlist.ui.activity.MovieActivity;
import com.ronakmanglani.watchlist.ui.activity.MovieDetailActivity;
import com.ronakmanglani.watchlist.ui.adapter.MovieAdapter;
import com.ronakmanglani.watchlist.model.Movie;
import com.ronakmanglani.watchlist.api.ApiHelper;
import com.ronakmanglani.watchlist.util.TextUtil;
import com.ronakmanglani.watchlist.api.VolleySingleton;
import com.ronakmanglani.watchlist.ui.view.PaddingDecorationView;
import org.json.JSONArray;
import org.json.JSONObject;
import butterknife.BindView;
import butterknife.BindBool;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
public class MovieListFragment extends Fragment implements MovieAdapter.OnMovieClickListener {
private Context context;
private Unbinder unbinder;
private MovieAdapter adapter;
private GridLayoutManager layoutManager;
private int pageToDownload;
private static final int TOTAL_PAGES = 999;
private int viewType;
private boolean isLoading;
private boolean isLoadingLocked;
@BindBool(R.bool.is_tablet) boolean isTablet;
@BindView(R.id.error_message) View errorMessage;
@BindView(R.id.progress_circle) View progressCircle;
@BindView(R.id.loading_more) View loadingMore;
@BindView(R.id.swipe_refresh) SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.movie_grid) RecyclerView recyclerView;
// Fragment lifecycle
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_movie_list,container,false);
context = getContext();
unbinder = ButterKnife.bind(this, v);
// Initialize variables
pageToDownload = 1;
viewType = getArguments().getInt(WatchlistApp.VIEW_TYPE);
// Setup RecyclerView
adapter = new MovieAdapter(context, this);
layoutManager = new GridLayoutManager(context, getNumberOfColumns());
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new PaddingDecorationView(context, R.dimen.recycler_item_padding));
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Load more if RecyclerView has reached the end and isn't already loading
if (layoutManager.findLastVisibleItemPosition() == adapter.movieList.size() - 1 && !isLoadingLocked && !isLoading) {
if (pageToDownload < TOTAL_PAGES) {
loadingMore.setVisibility(View.VISIBLE);
downloadMoviesList();
}
}
}
});
// Setup swipe refresh
swipeRefreshLayout.setColorSchemeResources(R.color.accent);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// Toggle visibility
errorMessage.setVisibility(View.GONE);
progressCircle.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
// Remove cache
VolleySingleton.getInstance().requestQueue.getCache().remove(getUrlToDownload(1));
// Download again
pageToDownload = 1;
adapter = null;
downloadMoviesList();
}
});
// Get the movies list
if (savedInstanceState == null || !savedInstanceState.containsKey(WatchlistApp.MOVIE_LIST)) {
downloadMoviesList();
} else {
adapter.movieList = savedInstanceState.getParcelableArrayList(WatchlistApp.MOVIE_LIST);
pageToDownload = savedInstanceState.getInt(WatchlistApp.PAGE_TO_DOWNLOAD);
isLoadingLocked = savedInstanceState.getBoolean(WatchlistApp.IS_LOCKED);
isLoading = savedInstanceState.getBoolean(WatchlistApp.IS_LOADING);
// Download again if stopped, else show list
if (isLoading) {
if (pageToDownload == 1) {
progressCircle.setVisibility(View.VISIBLE);
loadingMore.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
swipeRefreshLayout.setVisibility(View.GONE);
} else {
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.VISIBLE);
swipeRefreshLayout.setVisibility(View.VISIBLE);
}
downloadMoviesList();
} else {
onDownloadSuccessful();
}
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (layoutManager != null && adapter != null) {
outState.putBoolean(WatchlistApp.IS_LOADING, isLoading);
outState.putBoolean(WatchlistApp.IS_LOCKED, isLoadingLocked);
outState.putInt(WatchlistApp.PAGE_TO_DOWNLOAD, pageToDownload);
outState.putParcelableArrayList(WatchlistApp.MOVIE_LIST, adapter.movieList);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
VolleySingleton.getInstance().requestQueue.cancelAll(this.getClass().getName());
unbinder.unbind();
}
// JSON parsing and display
public String getUrlToDownload(int page) {
if (viewType == WatchlistApp.VIEW_TYPE_POPULAR) {
return ApiHelper.getMostPopularMoviesLink(getActivity(), page);
} else if (viewType == WatchlistApp.VIEW_TYPE_RATED) {
return ApiHelper.getHighestRatedMoviesLink(getActivity(), page);
} else if (viewType == WatchlistApp.VIEW_TYPE_UPCOMING) {
return ApiHelper.getUpcomingMoviesLink(getActivity(), page);
} else if (viewType == WatchlistApp.VIEW_TYPE_PLAYING) {
return ApiHelper.getNowPlayingMoviesLink(getActivity(), page);
}
return null;
}
private void downloadMoviesList() {
if (adapter == null) {
adapter = new MovieAdapter(context, this);
recyclerView.setAdapter(adapter);
}
String urlToDownload = getUrlToDownload(pageToDownload);
final JsonObjectRequest request = new JsonObjectRequest (
Request.Method.GET, urlToDownload, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
try {
JSONArray result = jsonObject.getJSONArray("results");
for (int i = 0; i < result.length(); i++) {
JSONObject movie = (JSONObject) result.get(i);
String poster = movie.getString("poster_path");
String overview = movie.getString("overview");
String year = movie.getString("release_date");
if (!TextUtil.isNullOrEmpty(year)) {
year = year.substring(0, 4);
}
String id = movie.getString("id");
String title = movie.getString("title");
String backdrop = movie.getString("backdrop_path");
String rating = movie.getString("vote_average");
Movie thumb = new Movie(id, title, year, overview, rating, poster, backdrop);
adapter.movieList.add(thumb);
}
// Load detail fragment if in tablet mode
if (isTablet && pageToDownload == 1 && adapter.movieList.size() > 0) {
((MovieActivity)getActivity()).loadDetailFragmentWith(adapter.movieList.get(0).id);
}
pageToDownload++;
onDownloadSuccessful();
} catch (Exception ex) {
// JSON parsing error
onDownloadFailed();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
// Network error
onDownloadFailed();
}
});
isLoading = true;
request.setTag(this.getClass().getName());
VolleySingleton.getInstance().requestQueue.add(request);
}
private void onDownloadSuccessful() {
isLoading = false;
errorMessage.setVisibility(View.GONE);
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
swipeRefreshLayout.setVisibility(View.VISIBLE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.setEnabled(true);
adapter.notifyDataSetChanged();
}
private void onDownloadFailed() {
isLoading = false;
if (pageToDownload == 1) {
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.setVisibility(View.GONE);
errorMessage.setVisibility(View.VISIBLE);
} else {
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
errorMessage.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
swipeRefreshLayout.setVisibility(View.VISIBLE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.setEnabled(true);
isLoadingLocked = true;
}
}
// Helper methods
public void refreshLayout() {
Parcelable state = layoutManager.onSaveInstanceState();
layoutManager = new GridLayoutManager(getContext(), getNumberOfColumns());
recyclerView.setLayoutManager(layoutManager);
layoutManager.onRestoreInstanceState(state);
}
public int getNumberOfColumns() {
// Get screen width
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float widthPx = displayMetrics.widthPixels;
if (isTablet) {
widthPx = widthPx / 3;
}
// Calculate desired width
SharedPreferences preferences = context.getSharedPreferences(WatchlistApp.TABLE_USER, Context.MODE_PRIVATE);
if (preferences.getInt(WatchlistApp.VIEW_MODE, WatchlistApp.VIEW_MODE_GRID) == WatchlistApp.VIEW_MODE_GRID) {
float desiredPx = getResources().getDimensionPixelSize(R.dimen.movie_card_width);
int columns = Math.round(widthPx / desiredPx);
return columns > 2 ? columns : 2;
} else {
float desiredPx = getResources().getDimensionPixelSize(R.dimen.movie_list_card_width);
int columns = Math.round(widthPx / desiredPx);
return columns > 1 ? columns : 1;
}
}
// Click events
@OnClick(R.id.try_again)
public void onTryAgainClicked() {
// Hide all views
errorMessage.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayout.setVisibility(View.GONE);
// Show progress circle
progressCircle.setVisibility(View.VISIBLE);
// Try to download the data again
pageToDownload = 1;
adapter = null;
downloadMoviesList();
}
@Override
public void onMovieClicked(int position) {
if (isTablet) {
((MovieActivity)getActivity()).loadDetailFragmentWith(adapter.movieList.get(position).id);
} else {
Intent intent = new Intent(context, MovieDetailActivity.class);
intent.putExtra(WatchlistApp.MOVIE_ID, adapter.movieList.get(position).id);
startActivity(intent);
}
}
}