package com.etiennelawlor.loop.fragments;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.etiennelawlor.loop.R;
import com.etiennelawlor.loop.adapters.VideoCommentsAdapter;
import com.etiennelawlor.loop.models.AccessToken;
import com.etiennelawlor.loop.network.ServiceGenerator;
import com.etiennelawlor.loop.network.VimeoService;
import com.etiennelawlor.loop.network.interceptors.AuthorizedNetworkInterceptor;
import com.etiennelawlor.loop.network.models.request.CommentPost;
import com.etiennelawlor.loop.network.models.response.AuthorizedUser;
import com.etiennelawlor.loop.network.models.response.Comment;
import com.etiennelawlor.loop.network.models.response.CommentsEnvelope;
import com.etiennelawlor.loop.network.models.response.User;
import com.etiennelawlor.loop.network.models.response.Video;
import com.etiennelawlor.loop.prefs.LoopPrefs;
import com.etiennelawlor.loop.ui.LoadingImageView;
import com.etiennelawlor.loop.utilities.DisplayUtility;
import com.etiennelawlor.loop.utilities.FontCache;
import com.etiennelawlor.loop.utilities.FormValidationUtility;
import com.etiennelawlor.loop.utilities.NetworkLogUtility;
import com.etiennelawlor.loop.utilities.NetworkUtility;
import com.etiennelawlor.loop.utilities.TrestleUtility;
import com.jakewharton.rxbinding.widget.RxTextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import jp.wasabeef.recyclerview.animators.SlideInUpAnimator;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.subscriptions.CompositeSubscription;
/**
* Created by etiennelawlor on 12/20/15.
*/
public class VideoCommentsFragment extends BaseFragment implements VideoCommentsAdapter.OnItemLongClickListener {
// region Constants
public static final int PAGE_SIZE = 60;
// endregion
// region Views
@BindView(R.id.comment_et)
EditText commentEditText;
@BindView(R.id.sumbit_comment_iv)
ImageView submitCommentImageView;
@BindView(R.id.sumbit_comment_pb)
ProgressBar submitCommentProgressBar;
@BindView(R.id.sumbit_comment_fl)
FrameLayout submitCommentFrameLayout;
@BindView(R.id.rv)
RecyclerView recyclerView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.loading_iv)
LoadingImageView loadingImageView;
@BindView(R.id.error_ll)
LinearLayout errorLinearLayout;
@BindView(R.id.error_tv)
TextView errorTextView;
// endregion
//region Member Variables
private VideoCommentsAdapter videoCommentsAdapter;
private VimeoService vimeoService;
private Video video;
private CompositeSubscription compositeSubscription;
private Observable<CharSequence> commentChangeObservable;
private int currentPage = 1;
private Long videoId = -1L;
private boolean commentChangeMade = false;
private boolean isLoading = false;
private boolean isLastPage = false;
private String sortByValue = "date";
private String sortOrderValue = "desc";
private Unbinder unbinder;
private Typeface font;
private Comment deletedComment;
// endregion
// region Listeners
@OnClick(R.id.sumbit_comment_fl)
public void submitComment() {
String comment = commentEditText.getText().toString();
if (!TextUtils.isEmpty(comment)) {
CommentPost commentPost = new CommentPost();
commentPost.setText(comment);
//
submitCommentFrameLayout.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.grey_200));
submitCommentImageView.setVisibility(View.GONE);
submitCommentProgressBar.setVisibility(View.VISIBLE);
Call addCommentCall = vimeoService.addComment(videoId, commentPost);
calls.add(addCommentCall);
addCommentCall.enqueue(addCommentCallback);
}
}
@OnClick(R.id.reload_btn)
public void onReloadButtonClicked() {
errorLinearLayout.setVisibility(View.GONE);
loadingImageView.setVisibility(View.VISIBLE);
Call getCommentsCall = vimeoService.getComments(videoId,
sortByValue,
sortOrderValue,
currentPage,
PAGE_SIZE);
calls.add(getCommentsCall);
getCommentsCall.enqueue(getCommentsFirstFetchCallback);
}
// endregion
// region Callbacks
private Callback<CommentsEnvelope> getCommentsFirstFetchCallback = new Callback<CommentsEnvelope>() {
@Override
public void onResponse(Call<CommentsEnvelope> call, Response<CommentsEnvelope> response) {
loadingImageView.setVisibility(View.GONE);
isLoading = false;
if (!response.isSuccessful()) {
int responseCode = response.code();
if(responseCode == 504) { // 504 Unsatisfiable Request (only-if-cached)
// errorTextView.setText("Can't load data.\nCheck your network connection.");
// errorLinearLayout.setVisibility(View.VISIBLE);
}
return;
}
CommentsEnvelope commentsEnvelope = response.body();
if (commentsEnvelope != null) {
List<Comment> comments = commentsEnvelope.getComments();
if (comments != null) {
if(comments.size()>0) {
Collections.reverse(comments);
videoCommentsAdapter.addAll(comments);
recyclerView.scrollToPosition(videoCommentsAdapter.getItemCount() - 1);
}
if (comments.size() >= PAGE_SIZE) {
// mVideoCommentsAdapter.addLoading();
} else {
isLastPage = true;
}
}
}
// if (mVideoCommentsAdapter.isEmpty()) {
// mEmptyTextView.setText(getString(R.string.watch_later_empty_prompt));
// Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.ic_watch_later_large);
// DrawableCompat.setTint(drawable, ContextCompat.getColor(getActivity(), R.color.grey_500));
// mEmptyTextView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
// mEmptyView.setVisibility(View.VISIBLE);
// }
}
@Override
public void onFailure(Call<CommentsEnvelope> call, Throwable t) {
NetworkLogUtility.logFailure(call, t);
if (!call.isCanceled()){
loadingImageView.setVisibility(View.GONE);
isLoading = false;
if(NetworkUtility.isKnownException(t)){
errorTextView.setText("Can't load data.\nCheck your network connection.");
errorLinearLayout.setVisibility(View.VISIBLE);
}
}
}
};
private Callback<Comment> addCommentCallback = new Callback<Comment>() {
@Override
public void onResponse(Call<Comment> call, Response<Comment> response) {
commentChangeMade = true;
submitCommentFrameLayout.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.primary));
submitCommentProgressBar.setVisibility(View.GONE);
submitCommentImageView.setVisibility(View.VISIBLE);
commentEditText.setText("");
DisplayUtility.hideKeyboard(getActivity(), commentEditText);
if (!response.isSuccessful()) {
int responseCode = response.code();
if(responseCode == 504) { // 504 Unsatisfiable Request (only-if-cached)
// errorTextView.setText("Can't load data.\nCheck your network connection.");
// errorLinearLayout.setVisibility(View.VISIBLE);
}
return;
}
Comment comment = response.body();
videoCommentsAdapter.add(comment);
recyclerView.scrollToPosition(videoCommentsAdapter.getItemCount()-1);
}
@Override
public void onFailure(Call<Comment> call, Throwable t) {
NetworkLogUtility.logFailure(call, t);
if (!call.isCanceled()){
submitCommentFrameLayout.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.primary));
submitCommentProgressBar.setVisibility(View.GONE);
submitCommentImageView.setVisibility(View.VISIBLE);
DisplayUtility.hideKeyboard(getActivity(), commentEditText);
if(NetworkUtility.isKnownException(t)){
Snackbar.make(getActivity().findViewById(R.id.main_content),
TrestleUtility.getFormattedText("Network connection is unavailable.", font, 16),
Snackbar.LENGTH_LONG)
.show();
}
}
}
};
private Callback<ResponseBody> deleteCommentCallback = new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
commentChangeMade = true;
if (!response.isSuccessful()) {
int responseCode = response.code();
if(responseCode == 504) { // 504 Unsatisfiable Request (only-if-cached)
// errorTextView.setText("Can't load data.\nCheck your network connection.");
// errorLinearLayout.setVisibility(View.VISIBLE);
}
return;
}
// Response 204 No Content
videoCommentsAdapter.remove(deletedComment);
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
NetworkLogUtility.logFailure(call, t);
if (!call.isCanceled()){
if(NetworkUtility.isKnownException(t)){
Snackbar.make(getActivity().findViewById(R.id.main_content),
TrestleUtility.getFormattedText("Network connection is unavailable.", font, 16),
Snackbar.LENGTH_LONG)
.show();
}
}
}
};
// endregion
// region Constructors
public VideoCommentsFragment() {
}
// endregion
// region Factory Methods
public static VideoCommentsFragment newInstance(Bundle extras) {
VideoCommentsFragment fragment = new VideoCommentsFragment();
fragment.setArguments(extras);
return fragment;
}
public static VideoCommentsFragment newInstance() {
return new VideoCommentsFragment();
}
//endregion
//region Lifecycle Methods
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Retain this fragment across configuration changes.
setRetainInstance(true);
if (getArguments() != null) {
video = (Video) getArguments().get(LikedVideosFragment.KEY_VIDEO);
}
AccessToken token = LoopPrefs.getAccessToken(getActivity());
vimeoService = ServiceGenerator.createService(
VimeoService.class,
VimeoService.BASE_URL,
new AuthorizedNetworkInterceptor(token));
font = FontCache.getTypeface("Ubuntu-Medium.ttf", getContext());
compositeSubscription = new CompositeSubscription();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_video_comments, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(final View view, Bundle bundle) {
super.onViewCreated(view, bundle);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(TrestleUtility.getFormattedText(getString(R.string.comments), font));
}
setUpListeners();
recyclerView.setItemAnimator(new SlideInUpAnimator());
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
layoutManager.setStackFromEnd(true);
// layoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new SlideInUpAnimator());
videoCommentsAdapter = new VideoCommentsAdapter(getActivity());
videoCommentsAdapter.setOnItemLongClickListener(this);
// List<Comment> comments = mSale.getComments();
// if (comments != null && comments.size() > 0) {
// Collections.reverse(comments);
// mVideoCommentsAdapter.addAll(comments);
// }
recyclerView.setAdapter(videoCommentsAdapter);
recyclerView.scrollToPosition(videoCommentsAdapter.getItemCount() - 1);
// if (commentsCollection != null) {
//// loadComments();
//
// List<Comment> comments = commentsCollection.getComments();
// if (comments != null && comments.size() > 0) {
//
// Collections.reverse(comments);
// videoCommentsAdapter.addAll(comments);
// recyclerView.scrollToPosition(videoCommentsAdapter.getItemCount() - 1);
////
//// mVideoCommentsAdapter.addAll(comments);
//
// if (comments.size() >= PAGE_SIZE) {
//// mVideoCommentsAdapter.addLoading();
// } else {
// isLastPage = true;
// }
// }
// } else {
//
// }
commentChangeObservable = RxTextView.textChanges(commentEditText);
// Checks for validity of the comment input field
setUpCommentSubscription();
long id = video.getId();
if (id != -1L) {
loadingImageView.setVisibility(View.VISIBLE);
videoId = id;
Call getCommentsCall = vimeoService.getComments(videoId,
sortByValue,
sortOrderValue,
currentPage,
PAGE_SIZE);
calls.add(getCommentsCall);
getCommentsCall.enqueue(getCommentsFirstFetchCallback);
}
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onDestroyView() {
super.onDestroyView();
removeListeners();
unbinder.unbind();
}
@Override
public void onDestroy() {
if (commentChangeMade) {
List<Comment> comments = new ArrayList<>();
for (int i = videoCommentsAdapter.getItemCount() - 1; i >= 0; i--) {
Comment comment = videoCommentsAdapter.getItem(i);
comments.add(comment);
}
}
super.onDestroy();
compositeSubscription.unsubscribe();
}
// endregion
// region VideoCommentsAdapter.OnItemLongClickListener Methods
@Override
public void onItemLongClick(final int position) {
final Comment comment = videoCommentsAdapter.getItem(position);
if (comment != null) {
deletedComment = comment;
User user = comment.getUser();
AuthorizedUser authorizedUser = LoopPrefs.getAuthorizedUser(getActivity());
if (user != null && authorizedUser != null) {
long commenterId = user.getId();
long loggedInUserId = authorizedUser.getId();
if (commenterId == loggedInUserId) {
AlertDialog.Builder deleteCommentAlert = new AlertDialog.Builder(getActivity(), R.style.DialogTheme);
deleteCommentAlert.setMessage("Are you sure you want to delete this comment?");
deleteCommentAlert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// videoCommentsAdapter.remove(comment);
// videoCommentsAdapter.notifyDataSetChanged();
Call deleteCommentCall = vimeoService.deleteComment(videoId,
comment.getId());
calls.add(deleteCommentCall);
deleteCommentCall.enqueue(deleteCommentCallback);
}
});
deleteCommentAlert.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
deleteCommentAlert.show();
}
}
}
}
// endregion
// region Helper Methods
private void setUpListeners() {
}
private void removeListeners() {
}
// private void loadComments() {
// List<Comment> comments = commentsCollection.getComments();
// if (comments != null && comments.size() > 0) {
//
// Collections.reverse(comments);
// videoCommentsAdapter.addAll(comments);
// recyclerView.scrollToPosition(videoCommentsAdapter.getItemCount() - 1);
////
//// mVideoCommentsAdapter.addAll(comments);
//
// if (comments.size() >= PAGE_SIZE) {
//// mVideoCommentsAdapter.addLoading();
// } else {
// isLastPage = true;
// }
// }
// }
private void setUpCommentSubscription(){
Subscription commentSubscription = commentChangeObservable
.observeOn(AndroidSchedulers.mainThread()) // UI Thread
.subscribe(new Subscriber<CharSequence>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(CharSequence charSequence) {
boolean isCommentValid = FormValidationUtility.validateComment(charSequence.toString());
if (!isCommentValid) {
disableSubmitComment();
} else {
enableSubmitComment();
}
}
});
compositeSubscription.add(commentSubscription);
}
private void enableSubmitComment(){
submitCommentImageView.setImageResource(R.drawable.ic_comment_active);
submitCommentFrameLayout.setEnabled(true);
}
private void disableSubmitComment(){
submitCommentImageView.setImageResource(R.drawable.ic_comment_inactive);
submitCommentFrameLayout.setEnabled(false);
}
// endregion
}