package io.github.xwz.base.api;
import android.util.Log;
import com.raizlabs.android.dbflow.list.FlowCursorList;
import com.raizlabs.android.dbflow.list.FlowQueryList;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Select;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import io.github.xwz.base.content.ContentCacheManager;
import io.github.xwz.base.content.ContentManagerBase;
public class ContentDatabaseCache {
private static final String TAG = "ContentDatabaseCache";
private static final String TYPE_EPISODES = "EPISODES";
private static final String TYPE_COLLECTIONS = "COLLECTIONS";
private static final String TYPE_SHOWS = "SHOWS";
public void clearCache() {
Log.d(TAG, "Clear db");
FlowQueryList<EpisodeBaseModel> query = new FlowQueryList<>(EpisodeBaseModel.class);
query.clear();
}
public void putShows(Collection<EpisodeBaseModel> shows) {
Log.d(TAG, "store shows into db");
FlowQueryList<EpisodeBaseModel> query = new FlowQueryList<>(EpisodeBaseModel.class);
query.beginTransaction();
for (EpisodeBaseModel ep : shows) {
EpisodeBaseModel model = new EpisodeBaseModel();
model.merge(ep);
model.DATA_TYPE = TYPE_EPISODES;
model.save();
}
query.endTransactionAndNotify();
}
public void putCollections(LinkedHashMap<String, List<EpisodeBaseModel>> collections) {
Log.d(TAG, "store collections into db");
int i = 0;
FlowQueryList<EpisodeBaseModel> query = new FlowQueryList<>(EpisodeBaseModel.class);
query.beginTransaction();
for (Map.Entry<String, List<EpisodeBaseModel>> collection : collections.entrySet()) {
Log.d(TAG, "Adding collection: " + collection.getKey() + " => " + collection.getValue().size());
updateProgress("Loading " + collection.getKey() + "...");
for (EpisodeBaseModel ep : collection.getValue()) {
EpisodeBaseModel model = new EpisodeBaseModel();
model.merge(ep);
model.DATA_TYPE = TYPE_COLLECTIONS;
model.DATA_COLLECTION_KEY = collection.getKey();
model.DATA_COLLECTION_INDEX = i++;
model.save();
}
}
query.endTransactionAndNotify();
}
private void updateProgress(String str) {
ContentManagerBase.getInstance().broadcastChange(ContentManagerBase.CONTENT_SHOW_LIST_PROGRESS, str);
}
public void putEpisodes(Collection<EpisodeBaseModel> episodes) {
Log.d(TAG, "store episodes into db");
FlowQueryList<EpisodeBaseModel> query = new FlowQueryList<>(EpisodeBaseModel.class);
query.beginTransaction();
for (EpisodeBaseModel ep : episodes) {
EpisodeBaseModel model = new EpisodeBaseModel();
model.merge(ep);
model.DATA_TYPE = TYPE_SHOWS;
model.save();
}
query.endTransactionAndNotify();
}
private List<EpisodeBaseModel> getModelsOfType(Class<?> model, String type, List<EpisodeBaseModel> existing, boolean uniqueSeries) {
FlowCursorList<EpisodeBaseModel> cursor = new FlowCursorList<>(false, EpisodeBaseModel.class,
Condition.column(EpisodeBaseModel$Table.DATA_TYPE).eq(type));
Map<String, EpisodeBaseModel> all = new HashMap<>();
for (int i = 0, k = cursor.getCount(); i < k; i++) {
EpisodeBaseModel ep = (EpisodeBaseModel) createInstanceOf(model);
if (ep != null) {
int index = existing.indexOf(ep);
if (index > -1) {
ep = existing.get(index);
} else {
EpisodeBaseModel item = cursor.getItem(i);
item.unserialize();
ep.merge(item);
}
if (uniqueSeries) {
all.put(ep.getSeriesTitle(), ep);
} else {
all.put(ep.getHref(), ep);
}
}
}
cursor.close();
return new ArrayList<>(all.values());
}
private Object createInstanceOf(Class<?> type) {
try {
Constructor<?> ctor = type.getConstructor();
Object object = ctor.newInstance();
return object;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private LinkedHashMap<String, List<EpisodeBaseModel>> getCollections(Class<?> model, List<EpisodeBaseModel> existing) {
LinkedHashMap<String, List<EpisodeBaseModel>> collections = new LinkedHashMap<>();
FlowCursorList<EpisodeBaseModel> cursor = new FlowCursorList<>(false,
(new Select()).from(EpisodeBaseModel.class)
.where(Condition.column(EpisodeBaseModel$Table.DATA_TYPE).eq(TYPE_COLLECTIONS))
.orderBy(true, EpisodeBaseModel$Table.DATA_COLLECTION_INDEX));
for (int i = 0, k = cursor.getCount(); i < k; i++) {
EpisodeBaseModel item = cursor.getItem(i);
item.unserialize();
int index = existing.indexOf(item);
EpisodeBaseModel ep;
if (index > -1) {
ep = existing.get(index);
} else {
ep = (EpisodeBaseModel) createInstanceOf(model);
if (ep != null) {
ep.merge(item);
}
}
if (ep != null) {
if (!collections.containsKey(item.DATA_COLLECTION_KEY)) {
collections.put(item.DATA_COLLECTION_KEY, new ArrayList<EpisodeBaseModel>());
}
collections.get(item.DATA_COLLECTION_KEY).add(ep);
}
}
for (Map.Entry<String, List<EpisodeBaseModel>> collection : collections.entrySet()) {
Log.d(TAG, "Loaded collection: " + collection.getKey() + " => " + collection.getValue().size());
}
return collections;
}
public boolean loadFromDbCache(ContentCacheManager cache, Class<?> type) {
updateProgress("Loading images...");
List<EpisodeBaseModel> episodes = getModelsOfType(type, TYPE_EPISODES, new ArrayList<EpisodeBaseModel>(), false);
if (episodes.size() > 0) {
updateProgress("Loading TV shows...");
List<EpisodeBaseModel> shows = getModelsOfType(type, TYPE_SHOWS, episodes, true);
updateProgress("Loading movies...");
LinkedHashMap<String, List<EpisodeBaseModel>> collections = getCollections(type, episodes);
cache.putEpisodes(episodes);
cache.putShows(shows);
cache.putCollections(collections);
updateProgress("Loading content...");
cache.buildDictionary(shows);
Log.d(TAG, "Loaded data from database");
return true;
}
return false;
}
}