/*
* Copyright 2015 Dmitry Monakhov.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package monakhv.android.samlib.adapter;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.bignerdranch.expandablerecyclerview.Adapter.ExpandableRecyclerAdapter;
import com.bignerdranch.expandablerecyclerview.Model.ParentListItem;
import com.bignerdranch.expandablerecyclerview.Model.ParentWrapper;
import monakhv.android.samlib.R;
import monakhv.android.samlib.data.SettingsHelper;
import monakhv.samlib.db.entity.Book;
import monakhv.samlib.db.entity.GroupBook;
import monakhv.samlib.db.entity.SamLibConfig;
import monakhv.samlib.log.Log;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import static monakhv.android.samlib.adapter.AuthorAdapter.DATE_FORMAT;
/**
* Base on this
* https://github.com/bignerdranch/expandable-recycler-view
* https://www.bignerdranch.com/blog/expand-a-recyclerview-in-four-steps/
* <p>
* Created by monakhv on 28.12.15.
*/
public class BookExpandableAdapter extends ExpandableRecyclerAdapter<GroupViewHolder, BookViewHolder> {
public interface CallBack {
void makeBookNewFlip(Book book);
void makeGroupNewFlip(GroupBook groupBook);
}
private static final String DEBUG_TAG = "BookExpandableAdapter";
private static final int NOT_SELECTED = -1;
private int selected = NOT_SELECTED;
public static final int TYPE_PARENT = 0;
private static final int TYPE_CHILD = 1;
private final LayoutInflater mInflater;
private final SettingsHelper mSettingsHelper;
private final int maxGroupId;
private long author_id;
private Context mContext;
private CallBack mCallBack;
private SimpleDateFormat df;
public BookExpandableAdapter(@NonNull List<? extends ParentListItem> parentItemList, int maxGroupId, Activity context, CallBack callBack, SettingsHelper settingsHelper) {
super(parentItemList);
this.maxGroupId = maxGroupId;
mInflater = LayoutInflater.from(context);
mCallBack = callBack;
mContext = context;
mSettingsHelper = settingsHelper;
setHasStableIds(true);
df = new SimpleDateFormat(DATE_FORMAT, Locale.FRANCE);
}
public void setAuthor_id(long author_id) {
this.author_id = author_id;
}
@Override
public GroupViewHolder onCreateParentViewHolder(ViewGroup viewGroup) {
View v = mInflater.inflate(R.layout.group_row, viewGroup, false);
return new GroupViewHolder(v, this);
}
@Override
public void onBindParentViewHolder(GroupViewHolder groupViewHolder, int position, ParentListItem parentListItem) {
GroupListItem gi = (GroupListItem) parentListItem;
groupViewHolder.groupTitle.setText(gi.getName());
if (gi.getId() == -1 && author_id != SamLibConfig.SELECTED_BOOK_ID) {
groupViewHolder.groupTitle.setText(mContext.getString(R.string.group_book_all));
}
if (gi.newNumber == 0) {
groupViewHolder.groupTitle.setTypeface(Typeface.DEFAULT);
groupViewHolder.bookNumber.setText(mContext.getString(R.string.group_book_number) + " " + gi.getChildItemList().size());
groupViewHolder.newIcon.setImageDrawable(groupViewHolder.oldGroupImage);
groupViewHolder.newIcon.setTag(0);
} else {
groupViewHolder.groupTitle.setTypeface(Typeface.DEFAULT_BOLD);
groupViewHolder.newIcon.setImageDrawable(groupViewHolder.newGroupImage);
groupViewHolder.newIcon.setTag(1);
groupViewHolder.bookNumber.setText(mContext.getString(R.string.group_book_number) + " " + gi.getChildItemList().size()
+ " "
+ mContext.getString(R.string.group_book_number_new)
+ " "
+ gi.newNumber);
}
if (gi.hidden) {
groupViewHolder.groupTitle.setAlpha(0.5f);
} else {
groupViewHolder.groupTitle.setAlpha(1.f);
}
}
@Override
public BookViewHolder onCreateChildViewHolder(ViewGroup viewGroup) {
View v = mInflater.inflate(R.layout.book_row_anim, viewGroup, false);
return new BookViewHolder(v, this);
}
public void flipCollapse(int position) {
ParentWrapper parentWrapper = (ParentWrapper) mItemList.get(position);
if (parentWrapper.isExpanded()) {
collapseParent(parentWrapper.getParentListItem());
} else {
expandParent(parentWrapper.getParentListItem());
}
}
@SuppressWarnings("deprecation")
@Override
public void onBindChildViewHolder(BookViewHolder holder, final int position, Object o) {
final Book book = (Book) o;
holder.bookTitle.setText(Html.fromHtml(book.getTitle()));
holder.bookTitle.setTag(book.getId());
try {
holder.bookDesc.setText(Html.fromHtml(book.getDescription()));
} catch (Exception ex) {//This is because of old book scheme where Description could be null
holder.bookDesc.setText("");
}
holder.bookAuthorName.setText(book.getAuthorName());
if (author_id != SamLibConfig.SELECTED_BOOK_ID) {
holder.bookAuthorName.setVisibility(View.GONE);
} else {
holder.bookAuthorName.setVisibility(View.VISIBLE);
holder.bookAuthorName.setTag(book.getAuthorId());
}
if (mSettingsHelper.isShowBookDate()){
holder.bookMTime.setVisibility(View.VISIBLE);
long dd = book.getModifyTime();
Date update = new Date(dd);
holder.bookMTime.setText(df.format(update));
}
else {
holder.bookMTime.setVisibility(View.GONE);
}
if (book.isIsNew() && book.getDelta() != 0) {
long delta = book.getDelta();
String str;
if (delta < 0) {
str = "" + book.getSize() + "K (" + delta + "K)";
} else {
str = "" + book.getSize() + "K (+" + delta + "K)";
}
holder.bookSize.setText(str);
} else {
holder.bookSize.setText(book.getSize() + "K");
}
holder.bookForm.setText(book.getForm());
if (book.isIsNew()) {
holder.bookTitle.setTypeface(Typeface.DEFAULT_BOLD);
holder.flipIcon.setImageDrawable(holder.openBook);
holder.flipIcon.setTag(1);
} else {
holder.bookTitle.setTypeface(Typeface.DEFAULT);
holder.flipIcon.setImageDrawable(holder.closeBook);
holder.flipIcon.setTag(0);
}
holder.itemView.setActivated(position == getSelectedPosition());
if (book.isSelected()) {
holder.starIcon.setImageResource(mSettingsHelper.getSelectedIcon());
holder.starIcon.setVisibility(View.VISIBLE);
} else {
holder.starIcon.setImageResource(R.drawable.rating_not_important);
holder.starIcon.setVisibility(View.INVISIBLE);
}
if (book.isPreserve()) {
holder.lockIcon.setImageResource(mSettingsHelper.getLockIcon());
holder.lockIcon.setVisibility(View.VISIBLE);
} else {
holder.lockIcon.setImageResource(R.drawable.rating_not_important);
holder.lockIcon.setVisibility(View.INVISIBLE);
}
}
@Override
public long getItemId(int position) {
int iType = getItemViewType(position);
Object o = mItemList.get(position);
if (iType == TYPE_PARENT) {
ParentWrapper pw = (ParentWrapper) o;
ParentListItem parentListItem = pw.getParentListItem();
GroupListItem gi = (GroupListItem) parentListItem;
return gi.getId();
}
if (iType == TYPE_CHILD) {
Book book = (Book) o;
return maxGroupId + book.getId();
}
throw new IllegalStateException("getItemId: Incorrect ViewType found");
}
/**
* update whole Book group
* @param groupListItem parentItem
* @param sort sort order currently not used
*/
public void updateData(GroupListItem groupListItem, int sort) {
//TODO: group Move is not implemented yet
if (groupListItem.getId() <0) {//Null Group
Log.d(DEBUG_TAG, "updateData1: change parent: 0!");
ParentListItem parentListItem = getParentItemList().get(0);
GroupListItem gi = (GroupListItem) parentListItem;
gi.newNumber =groupListItem.newNumber;
gi.setChildItemList(groupListItem.getChildItemList());
notifyParentItemChanged(0);
} else {
int parentListItemCount = getParentItemList().size();
for (int i = 0; i < parentListItemCount; i++) {
ParentListItem parentListItem = getParentItemList().get(i);
GroupListItem gi = (GroupListItem) parentListItem;
if (gi.getId() == groupListItem.getId()) {
gi.setChildItemList(groupListItem.getChildItemList());
gi.newNumber = groupListItem.newNumber;
Log.d(DEBUG_TAG, "updateData1: change parent: " + i);
notifyParentItemChanged(i);
return;
}
}
}
}
/**
* Update date using new Book and group Objects
*
* @param book Book
* @param group Group
* @param sort new position of Book in the group
*/
public void updateData(Book book, GroupBook group, int sort) {
int parentListItemCount = getParentItemList().size();
Log.d(DEBUG_TAG, "updateData2: parent list size: " + parentListItemCount);
ParentListItem parentListItem;
int iParent=group.getId();
for (int i = 0; i < parentListItemCount; i++) {//begin parent item cycle
parentListItem = getParentItemList().get(i);
GroupListItem gi = (GroupListItem) parentListItem;
if (gi.getId() == iParent) {//parent found if
gi.newNumber=group.getNewNumber();
gi.setGroupBook(group);
int idx = gi.getChildItemList().indexOf(book);
Log.d(DEBUG_TAG, "updateData2: parent item found at " +i+ " id: " + iParent+" book index: "+idx+" child list size: "+gi.getChildItemList().size());
if (idx != -1) {
if (sort == -1) {
gi.getChildItemList().remove(idx);
notifyChildItemRemoved(i,idx);
//notifyParentItemChanged(i);
} else {
gi.getChildItemList().remove(idx);
gi.getChildItemList().add(sort, book);
notifyChildItemMoved(i, idx, sort);
notifyParentItemChanged(i);
}
Log.d(DEBUG_TAG, "updateData2: update parent: " + i + " update child: " + idx + " -- " + getParentWrapperIndex(i));
return;
}
else {
for (Book b : gi.getChildItemList()){
Log.d(DEBUG_TAG,"updateData2: "+b.getId()+" - "+b.getUri());
}
}
}//parent found if
}//end parent item cycle
Log.w(DEBUG_TAG, "updateData2: No book found to update!");
}
/**
* Change selection position
* make notification by default
*
* @param position new selected item position
*/
public void toggleSelection(int position) {
toggleSelection(position, true);
}
/**
* Change selected element position
*
* @param position new selection position
* @param notified whether make change item notification or not
*/
private void toggleSelection(int position, boolean notified) {
if (position > 0 && getItemViewType(position) == 0) {
return;//ignore for parent type
}
if (position == selected) {
return;//selection is not changed - ignore it
}
int old_selection = selected;//preserve old selection position
selected = position;//new position
if (old_selection != NOT_SELECTED && notified) {
notifyItemChanged(old_selection);//clean up old selection
}
if (selected != NOT_SELECTED && notified) {
notifyItemChanged(selected);//make new selection
}
}
public void cleanSelection() {
toggleSelection(NOT_SELECTED);
}
private int getSelectedPosition() {
return selected;
}
public Book getSelected() {
int pos = getSelectedPosition();
Log.d(DEBUG_TAG, "getSelected: position = " + pos);
if (pos == NOT_SELECTED) {
Log.e(DEBUG_TAG, "getSelected: position is NOT_SELECTED");
return null;
}
if (mItemList == null) {
Log.e(DEBUG_TAG, "getSelected: itemList is null");
return null;
}
Object o = mItemList.get(pos);
if (o instanceof Book) {
return (Book) o;
} else {
return null;
}
}
/**
* Return the book for current position
*
* @param position the position for Book
* @return book or NULL if the position is not for Book object
*/
public Book getBook(int position) {
if (position < 0) {
return null;
}
Object o = mItemList.get(position);
if (!(o instanceof Book)) {
Log.e(DEBUG_TAG, "getBook wrong object type");
return null;
}
return (Book) o;
}
/**
* Make flip read of the Book or nothing if the position is not For Book
*
* @param position the position for Book
*/
public void makeRead(int position) {
Book book = getBook(position);
if (book != null) {
mCallBack.makeBookNewFlip(book);
}
}
public void makeAllRead(int position) {
Object o = mItemList.get(position);
if (o instanceof Book) {
Book book = (Book) o;
if (!book.isIsNew()) {
return;
}
mCallBack.makeBookNewFlip(book);
}
if (o instanceof ParentWrapper) {
Log.d(DEBUG_TAG, "makeAllRead: parent wrapper");
final ParentWrapper parentWrapper = (ParentWrapper) o;
final ParentListItem parentListItem = parentWrapper.getParentListItem();
final GroupListItem groupListItem = (GroupListItem) parentListItem;
if (groupListItem.newNumber == 0) {
Log.d(DEBUG_TAG, "makeAllRead: nothing to clean exiting");
return;
}
Log.d(DEBUG_TAG, "makeAllRead: call clean group: " + groupListItem.getName());
mCallBack.makeGroupNewFlip(groupListItem.getGroupBook());
}
}
private int getParentWrapperIndex(int parentIndex) {
int parentCount = 0;
int listItemCount = mItemList.size();
for (int i = 0; i < listItemCount; i++) {
if (mItemList.get(i) instanceof ParentWrapper) {
parentCount++;
if (parentCount > parentIndex) {
return i;
}
}
}
return -1;
}
}