/*
* 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.riddle.achievement;
import android.support.annotation.NonNull;
import android.util.Log;
import dan.dit.whatsthat.achievement.AchievementDataEvent;
import dan.dit.whatsthat.achievement.AchievementDataEventListener;
import dan.dit.whatsthat.achievement.AchievementProperties;
import dan.dit.whatsthat.riddle.achievement.holders.MiscAchievementHolder;
import dan.dit.whatsthat.riddle.types.PracticalRiddleType;
import dan.dit.whatsthat.solution.Solution;
import dan.dit.whatsthat.testsubject.TestSubject;
import dan.dit.whatsthat.util.compaction.CompactedDataCorruptException;
import dan.dit.whatsthat.util.compaction.Compacter;
/**
* Created by daniel on 13.05.15.
*/
public class AchievementDataRiddleGame extends AchievementProperties {
private static final int STATE_NONE = 0;
private static final int STATE_OPENING= 1;
public static final int STATE_OPENED = 2;
public static final int STATE_CLOSED = 3;
private static final String DATA_NAME = "riddlegame";
private static final String KEY_START_TIME = "start_time";
public static final String KEY_PLAYED_TIME = "played_time";
public static final String KEY_LAST_OPENED = "last_opened";
public static final String KEY_SOLVED = "solved";
private static final AchievementDataRiddleGame sNull = new AchievementDataRiddleGame
.NullObject();
private int mState = STATE_NONE;
public AchievementDataRiddleGame(PracticalRiddleType type) {
super(DATA_NAME + type.getFullName());
}
private AchievementDataRiddleGame(String name) {
super(name);
}
public static @NonNull AchievementDataRiddleGame getNullObject() {
return sNull;
}
// Nullobject that does nothing meaningful but implements the full interface
private static class NullObject extends AchievementDataRiddleGame {
private static final String NULL_DATA_NAME = "riddlegamedata_null";
public NullObject() {
super(NULL_DATA_NAME);
}
public boolean removeListener(AchievementDataEventListener listener) {return false;}
public void addListener(AchievementDataEventListener listener) {}
public void notifyListeners(AchievementDataEvent event) {}
public void enableSilentChanges(int eventType) {}
public void disableSilentChanges() {}
protected synchronized void resetData() {}
public synchronized void putValue(String key, Long value, long requiredValueToOldDelta) {}
public synchronized void putValues(String key1, Long value1, long reqDelta1, String key2,
Long value2, long reqDelta2, String key3, Long value3,
long reqDelta3) {}
public synchronized Long increment(String key, long delta, long baseValue) {return baseValue;}
}
public synchronized void loadGame(Compacter achievementData) {
if (mState == STATE_OPENED || mState == STATE_OPENING) {
Log.e("Achievement", "Trying to open already opened AchievementDataRiddleGame " + mName);
return;
}
mState = STATE_OPENING;
enableSilentChanges(AchievementDataEvent.EVENT_TYPE_DATA_CREATE);
resetData();
boolean initNew = true;
if (achievementData != null) {
try {
unloadData(achievementData);
initNew = false;
} catch (CompactedDataCorruptException e) {
initNew = true;
}
}
if (initNew) {
newGame();
} else {
openGame();
}
disableSilentChanges();
}
private void newGame() {
putValue(KEY_START_TIME, System.currentTimeMillis(), AchievementProperties.UPDATE_POLICY_ALWAYS);
openGame();
}
private boolean isDecliningInput() {
return mState != STATE_OPENING && mState != STATE_OPENED;
}
@Override
public synchronized Long increment(String key, long delta, long baseValue) {
if (isDecliningInput()) {
return baseValue;
}
return super.increment(key, delta, baseValue);
}
@Override
public synchronized void putValue(String key, Long value, long requiredValueToOldDelta) {
if (isDecliningInput()) {
return;
}
super.putValue(key, value, requiredValueToOldDelta);
}
public synchronized void putValues(String key1, Long value1, long reqDelta1, String key2, Long value2, long reqDelta2, String key3, Long value3, long reqDelta3) {
if (isDecliningInput()) {
return;
}
boolean hadSilentChanges = isSilentChangeMode();
if (!hadSilentChanges) {
enableSilentChanges(AchievementDataEvent.EVENT_TYPE_DATA_UPDATE);
}
putValue(key1, value1, reqDelta1);
putValue(key2, value2, reqDelta2);
putValue(key3, value3, reqDelta3);
if (!hadSilentChanges) {
disableSilentChanges();
}
}
private void openGame() {
putValue(KEY_LAST_OPENED, System.currentTimeMillis(), AchievementProperties.UPDATE_POLICY_ALWAYS);
mState = STATE_OPENED;
}
public int getState() {
return mState;
}
public long getCurrentPlayedTime() {
return getValue(KEY_PLAYED_TIME, 0L) + System.currentTimeMillis() - getValue
(KEY_LAST_OPENED, getValue(KEY_START_TIME, 0L));
}
public synchronized void closeGame(long solved) {
if (mState == STATE_CLOSED || mState == STATE_NONE) {
Log.e("Achievement", "Trying to close already closed or not yet opened AchievementDataRiddleGame " + mName);
return;
}
enableSilentChanges(AchievementDataEvent.EVENT_TYPE_DATA_CLOSE);
long playedTime = getCurrentPlayedTime();
Log.d("Achievement", "Played time after closing game: " + playedTime);
putValueIfBigger(KEY_PLAYED_TIME, playedTime);
putValue(KEY_SOLVED, solved);
mState = STATE_CLOSED;
disableSilentChanges();
if (isSolved() && TestSubject.isInitialized()) {
long totalTime = System.currentTimeMillis() - getValue(KEY_START_TIME, 0L);
AchievementPropertiesMapped<String> data = TestSubject.getInstance().getAchievementHolder().getMiscData();
data.enableSilentChanges(AchievementDataEvent.EVENT_TYPE_DATA_UPDATE);
data.putValue(MiscAchievementHolder.KEY_LAST_SOLVED_GAME_PLAYED_TIME, playedTime);
data.putValue(MiscAchievementHolder.KEY_LAST_SOLVED_GAME_TOTAL_TIME, totalTime);
data.disableSilentChanges();
}
}
public boolean isSolved() {
return getValue(AchievementDataRiddleGame.KEY_SOLVED, Solution.SOLVED_NOTHING) == Solution.SOLVED_COMPLETELY;
}
public boolean isCustom() {
return getValue(GameAchievement.KEY_DATA_IS_OF_CUSTOM_GAME, 0L) == 1L;
}
}