package com.afollestad.silk.caching;
import android.content.Context;
import android.os.Handler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SilkCache<ItemType extends SilkComparable<ItemType>> extends SilkCacheBase<ItemType> {
public SilkCache(Context context, String name, Class<?> cls, OnReadyCallback<ItemType> onReady) {
super(context, name, cls);
init(onReady);
}
public SilkCache(Context context, String name, Class<?> cls, OnReadyCallback<ItemType> onReady, Handler handler) {
super(context, name, cls, handler);
init(onReady);
}
private void init(final OnReadyCallback<ItemType> callback) {
if (callback == null) {
loadItems();
return;
}
Thread t = new Thread(new Runnable() {
@Override
public void run() {
loadItems();
getHandler().post(new Runnable() {
@Override
public void run() {
callback.onReady(SilkCache.this);
}
});
}
});
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
public final SilkCache<ItemType> add(ItemType item) {
add(0, item);
return this;
}
public final SilkCache<ItemType> add(int index, ItemType item) {
if (item == null) throw new IllegalArgumentException("You cannot add a null item.");
log("Item " + item.getSilkId() + " added to the cache.");
getBuffer().add(index, item);
markChanged();
return this;
}
public final SilkCache<ItemType> addAll(ItemType[] items) {
addAll(0, new ArrayList<ItemType>(Arrays.asList(items)));
return this;
}
public final SilkCache<ItemType> addAll(List<ItemType> items) {
addAll(0, items);
return this;
}
public final SilkCache<ItemType> addAll(int startIndex, ItemType[] items) {
addAll(startIndex, new ArrayList<ItemType>(Arrays.asList(items)));
return this;
}
public final SilkCache<ItemType> addAll(int startIndex, List<ItemType> items) {
if (items == null || items.size() == 0)
throw new IllegalArgumentException("You cannot add a null or empty collection.");
markChanged();
int index = startIndex;
for (ItemType item : items) {
getBuffer().add(index, item);
index++;
}
log("Added " + items.size() + " items to the cache at index " + startIndex);
return this;
}
public final SilkCache<ItemType> set(ItemType[] items) {
set(new ArrayList<ItemType>(Arrays.asList(items)));
return this;
}
public final SilkCache<ItemType> set(List<ItemType> items) {
getBuffer().clear();
getBuffer().addAll(items);
log("Cache overwritten with " + items.size() + " items");
markChanged();
return this;
}
public final SilkCache<ItemType> update(ItemType item) {
update(item, false);
return this;
}
public final SilkCache<ItemType> update(ItemType item, boolean addIfNotFound) {
if (item == null) throw new IllegalArgumentException("You cannot update a null item.");
log("Updating item " + item.getSilkId().toString() + "...");
boolean found = false;
for (int i = 0; i < getBuffer().size(); i++) {
if (item.equalTo(getBuffer().get(i))) {
log("Item " + item.getSilkId() + " updated at index " + i);
getBuffer().set(i, item);
found = true;
markChanged();
break;
}
}
if (!found) {
if (addIfNotFound) add(item);
else log("No item found in the cache for " + item.getSilkId());
}
return this;
}
public final ItemType find(ItemType item) {
int index = findIndex(item);
if (index == -1) return null;
return getBuffer().get(index);
}
public final int findIndex(ItemType item) {
if (item == null)
throw new IllegalArgumentException("You cannot search for a null item.");
log("Searching for " + item.getSilkId() + "...");
for (int i = 0; i < getBuffer().size(); i++) {
if (item.equalTo(getBuffer().get(i))) {
log("Found " + item.getSilkId() + " at index " + i);
return i;
}
}
log("Item " + item.getSilkId() + " not found.");
return -1;
}
public final void find(final ItemType item, final SimpleFindCallback<ItemType> callback) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
final int result = findIndex(item);
getHandler().post(new Runnable() {
@Override
public void run() {
if (callback != null) {
ItemType resultItem = null;
if (result > -1) resultItem = getBuffer().get(result);
callback.onFound(resultItem, result);
}
}
});
} catch (final Exception e) {
log("Find error: " + e.getMessage());
getHandler().post(new Runnable() {
@Override
public void run() {
if (callback != null && callback instanceof FindCallback)
((FindCallback) callback).onError(e);
}
});
}
}
});
t.setPriority(Thread.MAX_PRIORITY);
t.start();
}
public final SilkCache<ItemType> remove(int index) {
if (index == -1 || index > getBuffer().size() - 1)
throw new IndexOutOfBoundsException("Index " + index + " is larger than the cache size (" + getBuffer().size() + ")");
getBuffer().remove(index);
markChanged();
return this;
}
public final SilkCache<ItemType> remove(ItemType item) {
if (item == null) throw new IllegalArgumentException("You cannot remove a null item.");
int index = findIndex(item);
if (index > -1) remove(index);
return this;
}
public final SilkCache<ItemType> clear() {
log("Removed " + getBuffer().size() + " items from the cache.");
getBuffer().clear();
markChanged();
return this;
}
public final int size() {
return getBuffer().size();
}
public final List<ItemType> read() {
return getBuffer();
}
public interface SimpleCommitCallback {
public void onError(Exception e);
}
public interface CommitCallback extends SimpleCommitCallback {
public void onCommitted();
}
public interface SimpleFindCallback<ItemType> {
public void onFound(ItemType item, int index);
}
public interface FindCallback<ItemType> extends SimpleFindCallback<ItemType> {
public void onError(Exception e);
}
}