package net.dev123.yibo.service.cache;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import net.dev123.commons.Paging;
import net.dev123.commons.util.ListUtil;
import net.dev123.mblog.entity.Status;
import net.dev123.yibo.R;
import net.dev123.yibo.common.GlobalVars;
import net.dev123.yibo.common.StatusCatalog;
import net.dev123.yibo.db.LocalAccount;
import net.dev123.yibo.db.LocalStatus;
import net.dev123.yibo.db.StatusDao;
import net.dev123.yibo.service.cache.wrap.StatusWrap;
import net.dev123.yibo.service.task.Util;
import android.content.Context;
import android.content.res.Resources;
/*
* K:Integer;表示链表的下标
* V:StatusWrap;表示链表某位置的值
*/
public class MyHomeCache implements ListCache<StatusWrap, Status> {
private static final int REMAIN_LEVEL_LIGHT_COUNT = 60;
private static final int REMAIN_LEVEL_MODERATE_COUNT = 40;
private static final int REMAIN_LEVEL_WEIGHT_COUNT = 20;
private Context context;
private LocalAccount account = null;
private List<StatusWrap> listCache = null;
public MyHomeCache(Context context, LocalAccount account) {
listCache = new ArrayList<StatusWrap>();
listCache = Collections.synchronizedList(listCache);
this.account = account;
this.context = context;
}
@Override
public void clear() {
flush();
listCache.clear();
}
@Override
public boolean reclaim(ReclaimLevel level) {
int remainCount = size();
if (remainCount >= REMAIN_LEVEL_LIGHT_COUNT) {
level = ReclaimLevel.MODERATE;
}
switch(level) {
case LIGHT: remainCount = REMAIN_LEVEL_LIGHT_COUNT; break;
case MODERATE: remainCount = REMAIN_LEVEL_MODERATE_COUNT; break;
case WEIGHT: remainCount = REMAIN_LEVEL_WEIGHT_COUNT; break;
}
if (size() <= remainCount) {
return false;
}
while (size() > remainCount) {
listCache.remove(remainCount);
}
LocalStatus divider = new LocalStatus();
divider.setDivider(true);
divider.setLocalDivider(true);
StatusWrap wrap = new StatusWrap(divider);
listCache.add(wrap);
return true;
}
@Override
public void flush() {
StatusWrap wrap = null;
List<Status> listStatus = new ArrayList<Status>();
for (int i = 0; i < listCache.size(); i++) {
try {
wrap = listCache.get(i);
} catch(Exception e){
break;
}
if (wrap == null || wrap.isLocalCached()) {
continue;
}
Status status = wrap.getWrap();
if (status instanceof LocalStatus
&& ((LocalStatus)status).isLocalDivider()) {
continue;
}
listStatus.add(status);
wrap.setLocalCached(true);
}
if (listStatus.size() > 0) {
StatusDao dao = new StatusDao(context);
dao.batchSave(listStatus, StatusCatalog.Home, account);
}
}
@Override
public StatusWrap get(int i) {
if (i < 0 || i >= size()) {
return null;
}
StatusWrap wrap = null;
try {
wrap = listCache.get(i);
} catch(Exception e) {}
return wrap;
}
@Override
public void add(int i, StatusWrap value) {
if (i < 0 || i > size()) {
return;
}
listCache.add(i, value);
}
/** 默认是加前面 **/
@Override
public void add(StatusWrap value) {
listCache.add(0, value);
}
public void addAll(int i, List<StatusWrap> value) {
if (i < 0
|| i > size()
|| ListUtil.isEmpty(value)) {
return;
}
try {
listCache.addAll(i, value);
} catch (Exception e) {
listCache.addAll(size(), value);
}
}
public void addAll(List<StatusWrap> value) {
if (value == null || value.size() == 0) {
return;
}
addAll(0, value);
}
@Override
public void remove(int i) {
if (i < 0 || i >= size()) {
return;
}
StatusWrap sWrap = listCache.remove(i);
if (sWrap.getWrap() == null) {
return;
}
StatusDao dao = new StatusDao(context);
dao.delete(sWrap.getWrap(), account);
}
@Override
public void remove(StatusWrap value) {
if (value == null || value.getWrap() == null) {
return;
}
int i = indexOf(value);
if (i != -1) {
remove(i);
}
}
@Override
public List<StatusWrap> read(Paging<Status> page) {
List<StatusWrap> listWrap = null;
if (page == null || page.getPageSize() < 0 || page.getPageIndex() <= 0) {
return listWrap;
}
Resources res = context.getResources();
String[] querySqls = res.getStringArray(R.array.db_query_status_sql);
Status max = page.getMax();
Status since = page.getSince();
StringBuffer condition = new StringBuffer();
if (max != null) {
long maxCreatedAt = max.getCreatedAt().getTime();
String formatSegement = String.format(querySqls[1], maxCreatedAt);
condition.append(" " + formatSegement);
}
if (since != null) {
long sinceCreatedAt = since.getCreatedAt().getTime();
String formatSegement = String.format(querySqls[2], sinceCreatedAt);
condition.append(" " + formatSegement);
}
String sql = String.format(
querySqls[0], account.getAccountId(),
StatusCatalog.Home.getCatalogId(),
condition.toString());
StatusDao dao = new StatusDao(context);
List<Status> listStatus = dao.find(sql, 1, page.getPageSize());
if (ListUtil.isEmpty(listStatus)) {
return listWrap;
}
Status last = null;
last = listStatus.get(listStatus.size() - 1);
//如果最后一条刚好是间隔时,再读取一条
if (last instanceof LocalStatus
&& ((LocalStatus)last).isDivider()
&& listStatus.size() > 1) {
long maxCreatedAt = last.getCreatedAt().getTime();
String formatSegement = String.format(querySqls[1], maxCreatedAt);
sql = String.format(
querySqls[0], account.getAccountId(),
StatusCatalog.Home.getCatalogId(), formatSegement);
List<Status> listTemp = dao.find(sql.toString(), 1, 1);
if (ListUtil.isNotEmpty(listTemp)) {
listStatus.addAll(listTemp);
}
}
Util.getResponseCountsAsync(listStatus, GlobalVars.getMicroBlog(account));
Date currentDate = new Date();
listWrap = new ArrayList<StatusWrap>(listStatus.size());
StatusWrap wrap;
for (Status status : listStatus) {
wrap = new StatusWrap(status);
wrap.setLocalCached(true);
wrap.setReadedTime(currentDate);
wrap.setReaded(true);
listWrap.add(wrap);
}
//处理旧列表最后一条数据; XX在非ui线程导致崩溃XX
// last = null;
// if (size() > 0) {
// last = get(size() - 1).getWrap();
// }
// if (last != null
// && last instanceof LocalStatus
// && ((LocalStatus)last).isDivider()) {
// remove(size() - 1);
// }
//是否添加一条分隔
last = listStatus.get(listStatus.size() - 1);
if (!(last instanceof LocalStatus)
|| !((LocalStatus)last).isDivider()) {
LocalStatus divider = new LocalStatus();
divider.setDivider(true);
divider.setLocalDivider(true);
wrap = new StatusWrap(divider);
listWrap.add(wrap);
}
return listWrap;
}
@Override
public void write(StatusWrap value) {
if (value == null) {
return;
}
StatusDao dao = new StatusDao(context);
dao.save(value.getWrap(),StatusCatalog.Home, account);
value.setLocalCached(true);
}
@Override
public int indexOf(StatusWrap value) {
int index = -1;
if (value == null || value.getWrap() == null) {
return index;
}
for (int i = 0; i < size(); i++) {
StatusWrap temp = get(i);
if (temp == null) {
continue;
}
Status wrap = temp.getWrap();
if (wrap != null && wrap.equals(value.getWrap())) {
index = i;
break;
}
}
return index;
}
@Override
public int size() {
return listCache.size();
}
}