package im.actor.runtime.mvvm;
import java.util.HashSet;
import im.actor.runtime.annotations.MainThread;
public class LockableValue<T> extends Value<T> {
private ValueChangedListener<T> listener = new ValueChangedListener<T>() {
@Override
public void onChanged(T val, Value<T> valueModel) {
LockableValue.this.originalValue = val;
if (!isLockEnabled) {
notifyInMainThread(LockableValue.this.originalValue);
}
}
};
private Value<T> baseValue;
private T originalValue;
private T modifiedValue;
private boolean isLockEnabled = false;
private int NEXT_LOCK_ID = 0;
private HashSet<Integer> activeLocks = new HashSet<Integer>();
public LockableValue(String name, Value<T> baseValue) {
super(name);
this.baseValue = baseValue;
this.originalValue = baseValue.get();
baseValue.subscribe(listener);
}
@MainThread
public int createLock() {
// Check lock enable
if (activeLocks.size() == 0) {
modifiedValue = originalValue;
isLockEnabled = true;
}
// Creating lock id
int lockId = NEXT_LOCK_ID++;
activeLocks.add(lockId);
return lockId;
}
/**
* Can be executed only between create/release lock calls
*/
@MainThread
public void change(T obj) {
if (!isLockEnabled) {
throw new RuntimeException("changing of values only cen be performed in locked state");
}
modifiedValue = obj;
notifyInMainThread(modifiedValue);
}
@MainThread
public void releaseLock(int id) {
// Releasing lock
activeLocks.remove(id);
// Check lock disable
if (activeLocks.size() == 0) {
modifiedValue = null;
isLockEnabled = false;
notifyInMainThread(originalValue);
}
}
@Override
public T get() {
if (isLockEnabled) {
return modifiedValue;
} else {
return originalValue;
}
}
protected T getModifiedValue() {
return modifiedValue;
}
public void destroy() {
baseValue.unsubscribe(listener);
}
}