/*
* Copyright 2015 Daniel Dittmar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dan.dit.whatsthat.util.wallet;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.HashMap;
import java.util.Map;
import dan.dit.whatsthat.util.general.ObserverController;
/**
* A wallet is a single object hold by the TestSubject which contains
* various kinds of currencies, expenses, valuables and unlocked features that can be used.
* The wallet is updated only when the corresponding event happened and changes to the wallet are saved by the TestSubject
* and not validated again in the future.
* Created by daniel on 09.06.15.
*/
public class Wallet {
private static final String WALLET_FILE_NAME = "dan.dit.whatsthat.wallets";
private Map<String, WalletEntry> mEntries;
private Editor mEditor;
private SharedPreferences mPrefs;
private final String mName;
private ObserverController<OnEntryChangedListener, WalletEntry>
mOnEntryChangedListenerController = new ObserverController<>();
public interface OnEntryChangedListener extends ObserverController.Observer<WalletEntry>{
void onEntryRemoved(WalletEntry entry);
}
public Wallet(Context context, String name) {
mName = name;
mPrefs = context.getSharedPreferences(WALLET_FILE_NAME, Context.MODE_PRIVATE);
mEntries = new HashMap<>();
mEditor = new Editor();
}
public void removeEntry(String key) {
WalletEntry entry = mEntries.remove(key);
if (entry != null) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.remove(mName + key).apply();
notifyRemovedListeners(entry);
}
}
public WalletEntry assureEntry(String key) {
return assureEntry(key, WalletEntry.FALSE);
}
public WalletEntry assureEntry(String key, int defaultValue) {
WalletEntry entry = mEntries.get(key);
if (entry == null) {
synchronized (this) {
int loaded = mPrefs.getInt(mName + key, defaultValue);
entry = new WalletEntry(key, 0, loaded);
mEntries.put(key, entry);
mEditor.init(entry).apply();
}
}
return entry;
}
public int getEntryValue(String key) {
return assureEntry(key).getValue();
}
public int getEntryValue(String key, int defaultValue) {
return assureEntry(key, defaultValue).getValue();
}
public Editor editEntry(String key) {
return mEditor.init(assureEntry(key));
}
public Editor editEntry(String key, int defaultValue) {
return mEditor.init(assureEntry(key, defaultValue));
}
/**
* Editor of wallet entries. Each edit only accepts inputs that will
* increase the WalletEntry value, so setting to a smaller value, setting a true
* entry to false or negative deltas will do nothing.
* Depts can be implemented by a separate entry.
*/
public class Editor {
private WalletEntry mEntry;
private int mValue;
private Editor init(WalletEntry entry) {
mEntry = entry;
mValue = entry.getValue();
return this;
}
public boolean add(int delta) {
if (delta > 0) {
mValue = mEntry.getValue() + delta;
apply();
return true;
}
return false;
}
public boolean set(int value) {
if (value > mValue) {
mValue = value;
apply();
return true;
}
return false;
}
public boolean setTrue() {
if (mValue != WalletEntry.TRUE && mValue < WalletEntry.TRUE) {
mValue = WalletEntry.TRUE;
apply();
return true;
}
return false;
}
private void apply() {
SharedPreferences.Editor editor = mPrefs.edit();
int oldValue = mEntry.getValue();
mEntry.setValue(mValue);
editor.putInt(mName + mEntry.getKey(), mValue).apply();
if (oldValue != mValue) {
notifyChangedListeners(mEntry);
}
}
}
public void addChangedListener(OnEntryChangedListener listener) {
mOnEntryChangedListenerController.addObserver(listener);
}
public void removeChangedListener(OnEntryChangedListener listener) {
mOnEntryChangedListenerController.removeObserver(listener);
}
private void notifyChangedListeners(WalletEntry entry) {
mOnEntryChangedListenerController.notifyObservers(entry);
}
private void notifyRemovedListeners(WalletEntry entry) {
for (OnEntryChangedListener listener : mOnEntryChangedListenerController) {
listener.onEntryRemoved(entry);
}
}
}