package fr.ydelouis.selfoss.sync;
import android.content.Context;
import android.content.Intent;
import com.j256.ormlite.dao.Dao;
import org.androidannotations.annotations.AfterInject;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.OrmLiteDao;
import org.androidannotations.annotations.RootContext;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import fr.ydelouis.selfoss.entity.Article;
import fr.ydelouis.selfoss.model.ArticleDao;
import fr.ydelouis.selfoss.model.DatabaseHelper;
import fr.ydelouis.selfoss.rest.SelfossRestWrapper;
@EBean
public class ArticleSync {
public static final String ACTION_SYNC = "fr.ydelouis.selfoss.article.ACTION_SYNC";
public static final String ACTION_NEW_SYNCED = "fr.ydelouis.selfoss.article.ACTION_NEW_SYNCED";
private static final int ARTICLES_PAGE_SIZE = 20;
private static final int CACHE_SIZE = 50;
private static final long NOT_FAVORITE_ARTICLE_LIFETIME = TimeUnit.DAYS.toMillis(21);
@RootContext
protected Context context;
@Bean
protected SelfossRestWrapper selfossRest;
@OrmLiteDao(helper = DatabaseHelper.class)
protected ArticleDao articleDao;
@AfterInject
protected void init() {
articleDao.setContext(context);
}
public void performSync() {
String updateTime = articleDao.queryForLatestUpdateTime();
if (updateTime != null) {
syncUpdated(updateTime);
articleDao.deleteReadNotFavoriteAndNotCached();
} else {
syncCache();
syncUnread();
syncFavorite();
}
articleDao.deleteNotFavoriteOlderThan(new Date().getTime() - NOT_FAVORITE_ARTICLE_LIFETIME);
sendSyncBroadcast();
}
private void syncUpdated(String updateTime) {
int offset = 0;
List<Article> articles;
boolean newSynced = false;
do {
articles = selfossRest.listUpdatedArticles(offset, ARTICLES_PAGE_SIZE, updateTime);
for (Article article : articles) {
article.setCached(true);
Dao.CreateOrUpdateStatus status = articleDao.createOrUpdate(article);
if (article.isStarred() || article.isUnread() || status.isUpdated()) {
article.setCached(false);
articleDao.createOrUpdate(article);
article.setCached(true);
}
if (!newSynced && status.isUpdated()) {
sendNewSyncedBroadcast();
newSynced = true;
}
}
offset += ARTICLES_PAGE_SIZE;
} while (articles.size() == ARTICLES_PAGE_SIZE);
}
private void syncCache() {
int offset = 0;
List<Article> articles;
Article lastArticle = null;
boolean newSynced = false;
do {
articles = selfossRest.listArticles(offset, ARTICLES_PAGE_SIZE);
for (Article article : articles) {
article.setCached(true);
Dao.CreateOrUpdateStatus status = articleDao.createOrUpdate(article);
if (!newSynced && status.isUpdated()) {
sendNewSyncedBroadcast();
newSynced = true;
}
}
if (!articles.isEmpty()) {
lastArticle = articles.get(articles.size() - 1);
}
offset += ARTICLES_PAGE_SIZE;
} while (articles.size() == ARTICLES_PAGE_SIZE && offset < CACHE_SIZE);
if (lastArticle != null) {
articleDao.deleteCachedOlderThan(lastArticle.getDateTime());
}
}
private void syncUnread() {
articleDao.deleteUnread();
int offset = 0;
List<Article> articles;
do {
articles = selfossRest.listUnreadArticles(offset, ARTICLES_PAGE_SIZE);
for (Article article : articles) {
articleDao.createOrUpdate(article);
}
offset += ARTICLES_PAGE_SIZE;
} while (articles.size() == ARTICLES_PAGE_SIZE);
}
private void syncFavorite() {
articleDao.deleteFavorite();
int offset = 0;
List<Article> articles;
do {
articles = selfossRest.listStarredArticles(offset, ARTICLES_PAGE_SIZE);
for (Article article : articles) {
articleDao.createOrUpdate(article);
}
offset += ARTICLES_PAGE_SIZE;
} while (articles.size() == ARTICLES_PAGE_SIZE);
}
private void sendSyncBroadcast() {
context.sendBroadcast(new Intent(ArticleSync.ACTION_SYNC));
}
private void sendNewSyncedBroadcast() {
context.sendBroadcast(new Intent(ArticleSync.ACTION_NEW_SYNCED));
}
}