package com.ronakmanglani.watchlist.ui.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.ronakmanglani.watchlist.R;
import com.ronakmanglani.watchlist.WatchlistApp;
import com.ronakmanglani.watchlist.ui.activity.ReviewActivity;
import com.ronakmanglani.watchlist.ui.activity.ReviewDetailActivity;
import com.ronakmanglani.watchlist.ui.adapter.ReviewAdapter;
import com.ronakmanglani.watchlist.model.Review;
import com.ronakmanglani.watchlist.api.ApiHelper;
import com.ronakmanglani.watchlist.util.TextUtil;
import com.ronakmanglani.watchlist.api.VolleySingleton;
import org.json.JSONArray;
import org.json.JSONObject;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.BindBool;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
public class ReviewFragment extends Fragment implements ReviewAdapter.OnReviewClickListener {
private Unbinder unbinder;
private String movieId;
private String movieName;
private ReviewAdapter adapter;
private LinearLayoutManager layoutManager;
private int pageToDownload = 1;
private int totalPages = 1;
private boolean isLoading = false;
private boolean isLoadingLocked = false;
@BindBool(R.bool.is_tablet) boolean isTablet;
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.toolbar_title) TextView toolbarTitle;
@BindView(R.id.toolbar_subtitle) TextView toolbarSubtitle;
@BindView(R.id.review_list) RecyclerView reviewList;
@BindView(R.id.error_message) View errorMessage;
@BindView(R.id.no_results) View noResults;
@BindView(R.id.no_results_message) TextView noResultsMessage;
@BindView(R.id.progress_circle) View progressCircle;
@BindView(R.id.loading_more) View loadingMore;
// Fragment lifecycle
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_review,container,false);
unbinder = ButterKnife.bind(this, v);
// Initialize variables
movieId = getArguments().getString(WatchlistApp.MOVIE_ID);
movieName = getArguments().getString(WatchlistApp.MOVIE_NAME);
// Setup toolbar
toolbar.setTitle("");
toolbarTitle.setText(R.string.reviews_title);
toolbarSubtitle.setText(movieName);
toolbar.setNavigationIcon(ContextCompat.getDrawable(getActivity(), R.drawable.action_home));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getActivity().finish();
}
});
// Setup RecyclerView
adapter = new ReviewAdapter(new ArrayList<Review>(), this);
layoutManager = new LinearLayoutManager(getContext());
reviewList.setHasFixedSize(true);
reviewList.setLayoutManager(layoutManager);
reviewList.setAdapter(adapter);
reviewList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Load more data if reached the end of the list
if (layoutManager.findLastVisibleItemPosition() == adapter.reviewList.size() - 1 && !isLoadingLocked && !isLoading) {
if (pageToDownload < totalPages) {
loadingMore.setVisibility(View.VISIBLE);
downloadMovieReviews();
}
}
}
});
// Download reviews
if (savedInstanceState == null || !savedInstanceState.containsKey(WatchlistApp.REVIEW_LIST)) {
downloadMovieReviews();
} else {
adapter.reviewList = savedInstanceState.getParcelableArrayList(WatchlistApp.REVIEW_LIST);
totalPages = savedInstanceState.getInt(WatchlistApp.TOTAL_PAGES);
pageToDownload = savedInstanceState.getInt(WatchlistApp.PAGE_TO_DOWNLOAD);
isLoadingLocked = savedInstanceState.getBoolean(WatchlistApp.IS_LOCKED);
isLoading = savedInstanceState.getBoolean(WatchlistApp.IS_LOADING);
// If download stopped, download again, else display list
if (isLoading) {
if (pageToDownload > 1) {
progressCircle.setVisibility(View.GONE);
reviewList.setVisibility(View.VISIBLE);
loadingMore.setVisibility(View.VISIBLE);
}
downloadMovieReviews();
} else {
onDownloadSuccessful();
}
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (layoutManager != null && adapter != null) {
outState.putParcelableArrayList(WatchlistApp.REVIEW_LIST, adapter.reviewList);
outState.putBoolean(WatchlistApp.IS_LOADING, isLoading);
outState.putBoolean(WatchlistApp.IS_LOCKED, isLoadingLocked);
outState.putInt(WatchlistApp.PAGE_TO_DOWNLOAD, pageToDownload);
outState.putInt(WatchlistApp.TOTAL_PAGES, totalPages);
}
super.onSaveInstanceState(outState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
VolleySingleton.getInstance().requestQueue.cancelAll(this.getClass().getName());
unbinder.unbind();
}
// JSON parsing and display
private void downloadMovieReviews() {
if (adapter == null) {
adapter = new ReviewAdapter(new ArrayList<Review>(), this);
reviewList.setAdapter(adapter);
}
JsonArrayRequest request = new JsonArrayRequest(
Request.Method.GET, ApiHelper.getMovieReviewsLink(movieId, pageToDownload), null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray array) {
try {
for (int i = 0; i < array.length(); i++) {
JSONObject review = array.getJSONObject(i);
String id = review.getString("id");
String comment = review.getString("comment");
boolean hasSpoiler = review.getBoolean("spoiler");
// Get date and format it
String inputTime = review.getString("created_at").substring(0, 10);
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = inputFormat.parse(inputTime);
DateFormat outputFormat = new SimpleDateFormat("dd MMM yyyy");
String createdAt = outputFormat.format(date);
// Get user name
JSONObject user = review.getJSONObject("user");
String userName = user.getString("username");
if (!user.getBoolean("private")) {
String name = user.getString("name");
if (!TextUtil.isNullOrEmpty(name)) {
userName = name;
}
}
adapter.reviewList.add(new Review(id, userName, comment, createdAt, hasSpoiler));
}
onDownloadSuccessful();
} catch (Exception ex) {
// Parsing error
onDownloadFailed();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
if (volleyError.networkResponse.statusCode == 404 || volleyError.networkResponse.statusCode == 405) {
// No such movie exists
onDownloadSuccessful();
} else {
// Network error, failed to load
onDownloadFailed();
}
}
}) {
// Add Request Headers
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Content-type", "application/json");
params.put("trakt-api-key", ApiHelper.getTraktKey(getContext()));
params.put("trakt-api-version", "2");
return params;
}
// Get Response Headers
@Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
pageToDownload = Integer.parseInt(response.headers.get("X-Pagination-Page")) + 1;
totalPages = Integer.parseInt(response.headers.get("X-Pagination-Page-Count"));
return super.parseNetworkResponse(response);
}
};
isLoading = true;
request.setTag(getClass().getName());
VolleySingleton.getInstance().requestQueue.add(request);
}
private void onDownloadSuccessful() {
isLoading = false;
if (adapter.reviewList.size() == 0) {
noResultsMessage.setText(R.string.reviews_no_results);
noResults.setVisibility(View.VISIBLE);
errorMessage.setVisibility(View.GONE);
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
reviewList.setVisibility(View.GONE);
if (isTablet) {
((ReviewActivity) getActivity()).loadDetailFragmentWith("null", null);
}
} else {
errorMessage.setVisibility(View.GONE);
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
reviewList.setVisibility(View.VISIBLE);
adapter.notifyDataSetChanged();
if (isTablet) {
((ReviewActivity) getActivity()).loadDetailFragmentWith(movieName, adapter.reviewList.get(0));
}
}
}
private void onDownloadFailed() {
isLoading = false;
if (pageToDownload == 1) {
errorMessage.setVisibility(View.VISIBLE);
reviewList.setVisibility(View.GONE);
} else {
errorMessage.setVisibility(View.GONE);
reviewList.setVisibility(View.VISIBLE);
isLoadingLocked = true;
}
progressCircle.setVisibility(View.GONE);
loadingMore.setVisibility(View.GONE);
}
// Click events
@OnClick(R.id.try_again)
public void onTryAgainClicked() {
// Toggle visibility
reviewList.setVisibility(View.GONE);
errorMessage.setVisibility(View.GONE);
progressCircle.setVisibility(View.VISIBLE);
// Reset counters
pageToDownload = 1;
totalPages = 1;
// Download reviews again
adapter = null;
downloadMovieReviews();
}
@Override
public void onReviewClicked(int position) {
Review review = adapter.reviewList.get(position);
if (isTablet) {
((ReviewActivity) getActivity()).loadDetailFragmentWith(movieName, review);
} else {
Intent intent = new Intent(getContext(), ReviewDetailActivity.class);
intent.putExtra(WatchlistApp.MOVIE_NAME, movieName);
intent.putExtra(WatchlistApp.REVIEW_OBJECT, review);
startActivity(intent);
}
}
}