package jonathanfinerty.once;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class Once {
public static final int THIS_APP_INSTALL = 0;
public static final int THIS_APP_VERSION = 1;
private static long lastAppUpdatedTime = -1;
private static PersistedMap tagLastSeenMap;
private static PersistedSet toDoSet;
private Once() {
}
/**
* This method needs to be called before Once can be used.
* Typically it will be called from your Application class's onCreate method.
*
* @param context Application context
*/
public static void initialise(Context context) {
if (tagLastSeenMap == null) {
tagLastSeenMap = new PersistedMap(context, "TagLastSeenMap");
}
if (toDoSet == null) {
toDoSet = new PersistedSet(context, "ToDoSet");
}
PackageManager packageManager = context.getPackageManager();
try {
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
lastAppUpdatedTime = packageInfo.lastUpdateTime;
} catch (PackageManager.NameNotFoundException ignored) {
}
}
/**
* Mark a tag as 'to do' within a given scope, if it has already marked to do or been done
* within that scope then it will not be marked.
*
* @param scope The scope to not repeat the to do task in
* @param tag A string identifier unique to the operation.
* */
public static void toDo(int scope, String tag) {
Long tagLastSeenDate = tagLastSeenMap.get(tag);
if (tagLastSeenDate == null) {
toDoSet.put(tag);
return;
}
if (scope == THIS_APP_VERSION && tagLastSeenDate <= lastAppUpdatedTime) {
toDoSet.put(tag);
}
}
/**
* Mark a tag as 'to do' regardless of whether or not its ever been marked done before
* @param tag A string identifier unique to the operation.
* */
public static void toDo(String tag) {
toDoSet.put(tag);
}
/**
* Checks if a tag is currently marked as 'to do'.
*
* @param tag A string identifier unique to the operation.
* @return {@code true} if the operation associated with {@code tag} has been marked 'to do' and has not been passed to {@code markDone()} since.
* */
public static boolean needToDo(String tag) {
return toDoSet.contains(tag);
}
/**
* Checks if a tag has been marked done, ever.
*
* Equivalent of calling {@code beenDone(int scope, String tag)} with scope of {@code THIS_APP_INSTALL}.
*
* @param tag A string identifier unique to the operation.
* @return {@code true} if the operation associated with {@code tag} has been marked done within
* the given {@code scope}.
*/
public static boolean beenDone(String tag) {
return beenDone(THIS_APP_INSTALL, tag);
}
/**
* Checks if a tag has been marked done within a given scope.
*
* @param scope The scope in which to check whether the tag has been done, either
* {@code THIS_APP_INSTALL} or {@code THIS_APP_VERSION}.
* @param tag A string identifier unique to the operation.
* @return {@code true} if the operation associated with {@code tag} has been marked done within
* the given {@code scope}.
*/
public static boolean beenDone(int scope, String tag) {
Long tagLastSeenDate = tagLastSeenMap.get(tag);
if (tagLastSeenDate == null) {
return false;
}
if (scope == THIS_APP_INSTALL) {
return true;
}
return tagLastSeenDate > lastAppUpdatedTime;
}
/**
* Checks if a tag has been marked done within a given time span (e.g. the last 5 minutes)
*
* @param timeUnit The units of time to work in.
* @param amount The quantity of timeUnit.
* @param tag A string identifier unique to the operation.
* @return {@code true} if the operation associated with {@code tag} has been marked done
* within the last provide time span.
*/
public static boolean beenDone(TimeUnit timeUnit, long amount, String tag) {
long timeInMillis = timeUnit.toMillis(amount);
return beenDone(timeInMillis, tag);
}
/**
* Checks if a tag has been marked done within a the last X milliseconds
*
* @param timeSpanInMillis How many milliseconds ago to check if a tag has been marked done
* since.
* @param tag A string identifier unique to the operation.
* @return {@code true} if the operation associated with {@code tag} has been marked done
* within the last X milliseconds.
*/
public static boolean beenDone(long timeSpanInMillis, String tag) {
Long timeTagSeen = tagLastSeenMap.get(tag);
if (timeTagSeen == null) {
return false;
}
long sinceSinceCheckTime = new Date().getTime() - timeSpanInMillis;
return timeTagSeen > sinceSinceCheckTime;
}
/**
* Marks a tag (associated with some operation) as done. The tag is marked done at the time
* of calling this method
*
* @param tag A string identifier unique to the operation.
*/
public static void markDone(String tag) {
tagLastSeenMap.put(tag, new Date().getTime());
toDoSet.remove(tag);
}
/**
* Clears a tag as done. All checks with {@code beenDone()} with that tag will return true until
* it is marked done again.
*
* @param tag A string identifier unique to the operation.
*/
public static void clearDone(String tag) {
tagLastSeenMap.remove(tag);
}
/**
* Clears a tag as 'to do'. All checks with {@code needToDo()} with that tag will return false until
* it is marked 'to do' again.
*
* @param tag A string identifier unique to the operation.
*/
public static void clearToDo(String tag) {
toDoSet.remove(tag);
}
/**
* Clears all tags as done. All checks with {@code beenDone()} with any tag will return true
* until they are marked done again.
*/
public static void clearAll() {
tagLastSeenMap.clear();
}
/**
* Clears all tags as 'to do'. All checks with {@code needToDo()} with any tag will return {@code false}
* until they are marked 'to do' again.
*/
public static void clearAllToDos() {
toDoSet.clear();
}
}