/*
* Copyright (c) 2015 OpenSilk Productions LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package syncthing.android.ui.session;
import org.apache.commons.lang3.builder.RecursiveToStringStyle;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;
import rx.functions.Func1;
import syncthing.android.ui.common.Card;
import syncthing.android.ui.common.CardRecyclerAdapter;
import syncthing.android.ui.common.CardViewHolder;
import syncthing.android.ui.common.ExpandableCard;
/**
* Created by drew on 3/1/15.
*/
public class SessionRecyclerAdapter extends CardRecyclerAdapter {
final SessionPresenter mPresenter;
//order here is display order
List<NotifCard> notifications = new LinkedList<>();
HeaderCard folderHeader = HeaderCard.FOLDER;
List<FolderCard> folderItems = new LinkedList<>();
HeaderCard deviceHeader = HeaderCard.DEVICE;
MyDeviceCard thisDevice;
List<DeviceCard> deviceItems = new LinkedList<>();
public SessionRecyclerAdapter(SessionPresenter presenter) {
setHasStableIds(true);
mPresenter = presenter;
}
//for tests
SessionRecyclerAdapter() {
this(null);
}
@Override
public android.databinding.DataBindingComponent getBindingComponent() {
return mPresenter;
}
@Override
public void applyAdditionalBinding(Card card, CardViewHolder holder) {
// holder.getBinding().setVariable(syncthing.android.BR.clickHandler, this);
}
public void setNotifications(List<NotifCard> notifs, boolean notify) {
updateList(notifications, notifs, this::findNotificationOffset, notify);
}
public void setFolders(List<FolderCard> folders, boolean notify) {
updateList(folderItems, folders, this::findFolderOffset, notify);
}
public void setThisDevice(MyDeviceCard myDevice, boolean notify) {
boolean wasnull = thisDevice == null;
thisDevice = myDevice;
if (notify) {
if (wasnull) {
notifyItemInserted(findThisDevicePos());
} else {
notifyItemChanged(findThisDevicePos());
}
}
}
public void setDevices(List<DeviceCard> devices, boolean notify) {
updateList(deviceItems, devices, this::findDeviceOffset, notify);
}
<T extends ExpandableCard> void updateList(List<T> lst1, List<T> lst2, Func1<Integer, Integer> findFunc, boolean notify) {
if (lst1.isEmpty() && !lst2.isEmpty()) {
lst1.addAll(lst2);
if (notify) notifyItemRangeInserted(findFunc.call(0), lst2.size());
} else {
int oldsize = lst1.size();
int newsize = lst2.size();
lst1.clear();
lst1.addAll(lst2);
if (notify) {
if (oldsize == newsize) {
notifyItemRangeChanged(findFunc.call(0), oldsize);
} else if (oldsize < newsize) {
notifyItemRangeChanged(findFunc.call(0), oldsize);
notifyItemRangeInserted(findFunc.call(oldsize), newsize - oldsize);
} else {
notifyItemRangeChanged(findFunc.call(0), newsize);
notifyItemRangeRemoved(findFunc.call(newsize), oldsize - newsize);
}
}
}
}
/*
* finders locate relative adapter positon of items specified list
*/
int findNotificationOffset(int index) {
return index;
}
int findFolderOffset(int index) {
index = findNotificationOffset(index);
if (!notifications.isEmpty()) {
index += notifications.size();
}
if (folderHeader != null) {
index++;
}
return index;
}
int findThisDevicePos() {
return notifications.size()
+ ((folderHeader != null) ? 1 : 0)
+ folderItems.size()
+ ((deviceHeader != null) ? 1 : 0)
;
}
int findDeviceOffset(int index) {
index = findFolderOffset(index);
if (!folderItems.isEmpty()) {
index += folderItems.size();
}
if (deviceHeader != null) {
index++;
}
if (thisDevice != null) {
index++;
}
return index;
}
public Card getItem(int pos) {
final int origpos = pos;
if (pos < notifications.size()) {
return notifications.get(pos);
}
pos -= notifications.size();
if (folderHeader != null) {
if (pos == 0) {
return folderHeader;
}
pos--;
}
if (pos < folderItems.size()) {
return folderItems.get(pos);
}
pos -= folderItems.size();
if (deviceHeader != null) {
if (pos == 0) {
return deviceHeader;
}
pos--;
}
if (thisDevice != null) {
if (pos == 0) {
return thisDevice;
}
pos--;
}
if (pos < deviceItems.size()) {
return deviceItems.get(pos);
}
throw new IllegalArgumentException(dump() + ", pos " + pos + ", orig "+origpos);
}
@Override
public int getItemCount() {
return notifications.size()
+ ((folderHeader != null) ? 1 : 0)
+ folderItems.size()
+ ((deviceHeader != null) ? 1 : 0)
+ ((thisDevice != null) ? 1 : 0)
+ deviceItems.size()
;
}
@Override
public long getItemId(int position) {
return getItem(position).adapterId();
}
String dump() {
return ReflectionToStringBuilder.reflectionToString(this, RecursiveToStringStyle.MULTI_LINE_STYLE);
}
}