package com.quickblox.sample.chat.ui.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.quickblox.chat.model.QBAttachment;
import com.quickblox.chat.model.QBChatDialog;
import com.quickblox.chat.model.QBChatMessage;
import com.quickblox.core.helper.CollectionsUtil;
import com.quickblox.sample.chat.R;
import com.quickblox.sample.chat.ui.activity.AttachmentImageActivity;
import com.quickblox.sample.chat.ui.widget.MaskedImageView;
import com.quickblox.sample.chat.utils.Consts;
import com.quickblox.sample.chat.utils.TimeUtils;
import com.quickblox.sample.chat.utils.chat.ChatHelper;
import com.quickblox.sample.chat.utils.qb.PaginationHistoryListener;
import com.quickblox.sample.chat.utils.qb.QbUsersHolder;
import com.quickblox.sample.core.ui.adapter.BaseListAdapter;
import com.quickblox.sample.core.utils.ResourceUtils;
import com.quickblox.users.model.QBUser;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import java.util.Collection;
import java.util.List;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
public class ChatAdapter extends BaseListAdapter<QBChatMessage> implements StickyListHeadersAdapter {
private static final String TAG = ChatAdapter.class.getSimpleName();
private final QBChatDialog chatDialog;
private OnItemInfoExpandedListener onItemInfoExpandedListener;
private PaginationHistoryListener paginationListener;
private int previousGetCount = 0;
public ChatAdapter(Context context, QBChatDialog chatDialog, List<QBChatMessage> chatMessages) {
super(context, chatMessages);
this.chatDialog = chatDialog;
}
public void setOnItemInfoExpandedListener(OnItemInfoExpandedListener onItemInfoExpandedListener) {
this.onItemInfoExpandedListener = onItemInfoExpandedListener;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_item_chat_message, parent, false);
holder.messageBodyTextView = (TextView) convertView.findViewById(R.id.text_image_message);
holder.messageAuthorTextView = (TextView) convertView.findViewById(R.id.text_message_author);
holder.messageContainerLayout = (LinearLayout) convertView.findViewById(R.id.layout_chat_message_container);
holder.messageBodyContainerLayout = (RelativeLayout) convertView.findViewById(R.id.layout_message_content_container);
holder.messageInfoTextView = (TextView) convertView.findViewById(R.id.text_message_info);
holder.attachmentImageView = (MaskedImageView) convertView.findViewById(R.id.image_message_attachment);
holder.attachmentProgressBar = (ProgressBar) convertView.findViewById(R.id.progress_message_attachment);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final QBChatMessage chatMessage = getItem(position);
setIncomingOrOutgoingMessageAttributes(holder, chatMessage);
setMessageBody(holder, chatMessage);
setMessageInfo(chatMessage, holder);
setMessageAuthor(holder, chatMessage);
holder.messageContainerLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hasAttachments(chatMessage)) {
Collection<QBAttachment> attachments = chatMessage.getAttachments();
QBAttachment attachment = attachments.iterator().next();
AttachmentImageActivity.start(context, attachment.getUrl());
} else {
toggleItemInfo(holder, position);
}
}
});
holder.messageContainerLayout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (hasAttachments(chatMessage)) {
toggleItemInfo(holder, position);
return true;
}
return false;
}
});
holder.messageInfoTextView.setVisibility(View.GONE);
if (isIncoming(chatMessage) && !isRead(chatMessage)){
readMessage(chatMessage);
}
downloadMore(position);
return convertView;
}
private void downloadMore(int position) {
if (position == 0) {
if (getCount() != previousGetCount) {
paginationListener.downloadMore();
previousGetCount = getCount();
}
}
}
public void setPaginationHistoryListener(PaginationHistoryListener paginationListener) {
this.paginationListener = paginationListener;
}
private void toggleItemInfo(ViewHolder holder, int position) {
boolean isMessageInfoVisible = holder.messageInfoTextView.getVisibility() == View.VISIBLE;
holder.messageInfoTextView.setVisibility(isMessageInfoVisible ? View.GONE : View.VISIBLE);
if (onItemInfoExpandedListener != null) {
onItemInfoExpandedListener.onItemInfoExpanded(position);
}
}
@Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder;
if (convertView == null) {
holder = new HeaderViewHolder();
convertView = inflater.inflate(R.layout.view_chat_message_header, parent, false);
holder.dateTextView = (TextView) convertView.findViewById(R.id.header_date_textview);
convertView.setTag(holder);
} else {
holder = (HeaderViewHolder) convertView.getTag();
}
QBChatMessage chatMessage = getItem(position);
holder.dateTextView.setText(TimeUtils.getDate(chatMessage.getDateSent() * 1000));
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) holder.dateTextView.getLayoutParams();
if (position == 0) {
lp.topMargin = ResourceUtils.getDimen(R.dimen.chat_date_header_top_margin);
} else {
lp.topMargin = 0;
}
holder.dateTextView.setLayoutParams(lp);
return convertView;
}
@Override
public long getHeaderId(int position) {
QBChatMessage chatMessage = getItem(position);
return TimeUtils.getDateAsHeaderId(chatMessage.getDateSent() * 1000);
}
private void setMessageBody(final ViewHolder holder, QBChatMessage chatMessage) {
if (hasAttachments(chatMessage)) {
Collection<QBAttachment> attachments = chatMessage.getAttachments();
QBAttachment attachment = attachments.iterator().next();
holder.messageBodyTextView.setVisibility(View.GONE);
holder.attachmentImageView.setVisibility(View.VISIBLE);
holder.attachmentProgressBar.setVisibility(View.VISIBLE);
Glide.with(context)
.load(attachment.getUrl())
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model,
Target<GlideDrawable> target, boolean isFirstResource) {
e.printStackTrace();
holder.attachmentImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
holder.attachmentProgressBar.setVisibility(View.GONE);
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model,
Target<GlideDrawable> target,
boolean isFromMemoryCache, boolean isFirstResource) {
holder.attachmentImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.attachmentProgressBar.setVisibility(View.GONE);
return false;
}
})
.override(Consts.PREFERRED_IMAGE_SIZE_PREVIEW, Consts.PREFERRED_IMAGE_SIZE_PREVIEW)
.dontTransform()
.error(R.drawable.ic_error)
.into(holder.attachmentImageView);
} else {
holder.messageBodyTextView.setText(chatMessage.getBody());
holder.messageBodyTextView.setVisibility(View.VISIBLE);
holder.attachmentImageView.setVisibility(View.GONE);
holder.attachmentProgressBar.setVisibility(View.GONE);
}
}
private void setMessageAuthor(ViewHolder holder, QBChatMessage chatMessage) {
if (isIncoming(chatMessage)) {
QBUser sender = QbUsersHolder.getInstance().getUserById(chatMessage.getSenderId());
holder.messageAuthorTextView.setText(sender.getFullName());
holder.messageAuthorTextView.setVisibility(View.VISIBLE);
if (hasAttachments(chatMessage)) {
holder.messageAuthorTextView.setBackgroundResource(R.drawable.shape_rectangle_semi_transparent);
holder.messageAuthorTextView.setTextColor(ResourceUtils.getColor(R.color.text_color_white));
} else {
holder.messageAuthorTextView.setBackgroundResource(0);
holder.messageAuthorTextView.setTextColor(ResourceUtils.getColor(R.color.text_color_dark_grey));
}
} else {
holder.messageAuthorTextView.setVisibility(View.GONE);
}
}
private void setMessageInfo(QBChatMessage chatMessage, ViewHolder holder) {
holder.messageInfoTextView.setText(TimeUtils.getTime(chatMessage.getDateSent() * 1000));
}
@SuppressLint("RtlHardcoded")
private void setIncomingOrOutgoingMessageAttributes(ViewHolder holder, QBChatMessage chatMessage) {
boolean isIncoming = isIncoming(chatMessage);
int gravity = isIncoming ? Gravity.LEFT : Gravity.RIGHT;
holder.messageContainerLayout.setGravity(gravity);
holder.messageInfoTextView.setGravity(gravity);
int messageBodyContainerBgResource = isIncoming
? R.drawable.incoming_message_bg
: R.drawable.outgoing_message_bg;
if (hasAttachments(chatMessage)) {
holder.messageBodyContainerLayout.setBackgroundResource(0);
holder.messageBodyContainerLayout.setPadding(0, 0, 0, 0);
holder.attachmentImageView.setMaskResourceId(messageBodyContainerBgResource);
} else {
holder.messageBodyContainerLayout.setBackgroundResource(messageBodyContainerBgResource);
}
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) holder.messageAuthorTextView.getLayoutParams();
if (isIncoming && hasAttachments(chatMessage)) {
lp.leftMargin = ResourceUtils.getDimen(R.dimen.chat_message_attachment_username_margin);
lp.topMargin = ResourceUtils.getDimen(R.dimen.chat_message_attachment_username_margin);
} else if (isIncoming) {
lp.leftMargin = ResourceUtils.getDimen(R.dimen.chat_message_username_margin);
lp.topMargin = 0;
}
holder.messageAuthorTextView.setLayoutParams(lp);
int textColorResource = isIncoming
? R.color.text_color_black
: R.color.text_color_white;
holder.messageBodyTextView.setTextColor(ResourceUtils.getColor(textColorResource));
}
private boolean hasAttachments(QBChatMessage chatMessage) {
Collection<QBAttachment> attachments = chatMessage.getAttachments();
return attachments != null && !attachments.isEmpty();
}
private boolean isIncoming(QBChatMessage chatMessage) {
QBUser currentUser = ChatHelper.getCurrentUser();
return chatMessage.getSenderId() != null && !chatMessage.getSenderId().equals(currentUser.getId());
}
private boolean isRead(QBChatMessage chatMessage){
Integer currentUserId = ChatHelper.getCurrentUser().getId();
return !CollectionsUtil.isEmpty(chatMessage.getReadIds()) && chatMessage.getReadIds().contains(currentUserId);
}
private void readMessage(QBChatMessage chatMessage){
try {
chatDialog.readMessage(chatMessage);
} catch (XMPPException | SmackException.NotConnectedException e) {
Log.w(TAG, e);
}
}
private static class HeaderViewHolder {
public TextView dateTextView;
}
private static class ViewHolder {
public TextView messageBodyTextView;
public TextView messageAuthorTextView;
public TextView messageInfoTextView;
public LinearLayout messageContainerLayout;
public RelativeLayout messageBodyContainerLayout;
public MaskedImageView attachmentImageView;
public ProgressBar attachmentProgressBar;
}
public interface OnItemInfoExpandedListener {
void onItemInfoExpanded(int position);
}
}