package io.nextop.demo.flip;
import com.google.common.primitives.Ints;
import io.nextop.Id;
import io.nextop.rx.RxManaged;
import javax.annotation.Nullable;
import java.util.*;
public class FeedViewModel extends RxManaged {
List<FlipState> orderedStates = new ArrayList<FlipState>(8);
Map<Id, FlipState> states = new HashMap<Id, FlipState>(8);
long maxUpdateIndex = 0L;
long minUpdateIndex = 0L;
// FIXME remove
int k = 20;
int[][] shuffle = new int[k][];
{
Random r = new Random();
for (int i = 0; i < k; ++i) {
int n = 100;
int[] s = new int[n];
for (int j = 0; j < n; ++j) {
s[j] = j;
}
for (int j = n - 1; 0 < j; --j) {
int index = r.nextInt(j + 1);
int t = s[index];
s[index] = s[j];
s[j] = t;
}
shuffle[i] = s;
}
}
public FeedViewModel(Id feedId) {
super(feedId);
}
public int size() {
return /* FIXME remove */ k * orderedStates.size();
}
public Id getFlipId(int index) {
// FIXME remove
int n = orderedStates.size();
int i = index / n;
int[] s = shuffle[i];
int j = index % n;
if (0 < i && j < s.length) {
j = s[j];
while (n <= j) {
j /= 2;
}
}
return orderedStates.get(j).flipId;
}
void add(FlipState state) {
@Nullable FlipState pstate = states.put(state.flipId, state);
if (null != pstate) {
orderedStates.remove(pstate);
}
orderedStates.add(state);
Collections.sort(orderedStates, C_BY_UPDATE_INDEX);
if (0 < state.updateIndex) {
if (maxUpdateIndex < state.updateIndex) {
maxUpdateIndex = state.updateIndex;
} else if (state.updateIndex < minUpdateIndex) {
minUpdateIndex = state.updateIndex;
}
}
}
void remove(Id frameId) {
@Nullable FlipState state = states.remove(frameId);
if (null != state) {
orderedStates.remove(state);
}
}
long getMaxUpdateIndex() {
return maxUpdateIndex;
}
long getMinUpdateIndex() {
return minUpdateIndex;
}
static final class FlipState {
final Id flipId;
final long updateIndex;
FlipState(Id flipId, long updateIndex) {
this.flipId = flipId;
this.updateIndex = updateIndex;
}
}
private static final Comparator<FlipState> C_BY_UPDATE_INDEX = new Comparator<FlipState>() {
@Override
public int compare(FlipState a, FlipState b) {
// negative (pending) first, then descending
boolean an = a.updateIndex < 0;
boolean bn = b.updateIndex < 0;
if (an && bn) {
return 0;
} else if (an) {
return -1;
} else if (bn) {
return 1;
} else {
if (a.updateIndex < b.updateIndex) {
return 1;
}
if (b.updateIndex < a.updateIndex) {
return -1;
}
return 0;
}
}
};
}