/*
* Copyright (c) 2012. HappyDroids LLC, All rights reserved.
*/
package com.happydroids.droidtowers.achievements;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.happydroids.droidtowers.entities.Player;
import com.happydroids.droidtowers.types.GridObjectType;
import com.happydroids.droidtowers.types.GridObjectTypeFactory;
import com.happydroids.droidtowers.types.ProviderType;
import static com.happydroids.droidtowers.achievements.AchievementThing.ACHIEVEMENT;
import static com.happydroids.droidtowers.achievements.AchievementThing.OBJECT_TYPE;
import static com.happydroids.droidtowers.achievements.RewardType.UNLOCK;
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class Reward {
private RewardType type;
private AchievementThing thing;
private ProviderType[] thingProviderTypes;
private String thingId;
private double amount;
public Reward() {
}
public Reward(RewardType type, AchievementThing thing) {
this(type, thing, 0);
}
public Reward(RewardType type, AchievementThing thing, int amount) {
this.type = type;
this.thing = thing;
this.amount = amount;
}
public Reward(RewardType type, AchievementThing objectType, String objectTypeId) {
this.type = type;
thing = objectType;
thingId = objectTypeId;
}
public void give() {
if (type == null) {
throw new RuntimeException("Reward does not contain 'type' parameter.");
} else if (thing == null) {
throw new RuntimeException(String.format("Reward %s does not contain 'thing' parameter.", type));
}
switch (type) {
case GIVE:
handleGiveReward();
break;
case UNLOCK:
handleUnlockReward();
break;
case COMPLETE:
if (thing.equals(ACHIEVEMENT)) {
if (AchievementEngine.instance().findById(thingId) != null) {
AchievementEngine.instance().complete(thingId);
} else if (TutorialEngine.instance().findById(thingId) != null) {
TutorialEngine.instance().complete(thingId);
} else {
throw new RuntimeException("Could not find Achievement with id: " + thingId);
}
}
break;
}
}
private void handleGiveReward() {
switch (thing) {
case MONEY:
Player.instance().addCurrency((int) amount);
break;
}
}
private void handleUnlockReward() {
switch (thing) {
case OBJECT_TYPE:
getThingObjectType().removeLock();
break;
case PROVIDER_TYPE:
handleProviderTypeReward();
break;
case ACHIEVEMENT:
Achievement.findById(thingId).removeLock();
break;
}
}
private void handleProviderTypeReward() {
if (thingProviderTypes == null || thingProviderTypes.length == 0) {
throw new RuntimeException("Reward with 'thing' value of 'PROVIDER_TYPE' needs the parameter 'thingProviderTypes' to be set.");
}
setProviderTypeLockState(false);
}
private void setProviderTypeLockState(boolean locked) {
if (thingProviderTypes == null || thingProviderTypes.length == 0) {
throw new RuntimeException("Reward with 'thing' value of 'PROVIDER_TYPE' needs the parameter 'thingProviderTypes' to be set.");
}
for (ProviderType providerType : thingProviderTypes) {
for (GridObjectTypeFactory typeFactory : GridObjectTypeFactory.allFactories()) {
for (Object objectType : typeFactory.findByProviderType(providerType)) {
GridObjectType gridObjectType = (GridObjectType) objectType;
if (gridObjectType.provides(providerType)) {
if (locked) {
gridObjectType.addLock(this);
} else if (gridObjectType.getLock() == this) {
gridObjectType.removeLock();
}
}
}
}
}
}
protected GridObjectType getThingObjectType() {
if (thing == OBJECT_TYPE && thingId != null) {
GridObjectType objectType = GridObjectTypeFactory.findTypeById(thingId);
if (objectType == null) {
throw new RuntimeException(String.format("Cannot find a type for: %s", thingId));
}
return objectType;
}
throw new RuntimeException("Cannot find a type for null!");
}
public void resetState() {
if (type.equals(UNLOCK)) {
switch (thing) {
case OBJECT_TYPE:
getThingObjectType().addLock(this);
break;
case PROVIDER_TYPE:
setProviderTypeLockState(true);
break;
case ACHIEVEMENT:
Achievement.findById(thingId).addLock(this);
break;
}
}
}
public String getRewardString(boolean pastTense) {
return displayStringForType() + (pastTense ? "ed" : "") + " " + AchievementThing.displayStringForThing(thing, amount, thingId, thingProviderTypes);
}
private String displayStringForType() {
switch (type) {
case GIVE:
return "Award";
case UNLOCK:
return "Unlock";
}
return "";
}
public RewardType getType() {
return type;
}
public AchievementThing getThing() {
return thing;
}
public void unlock() {
switch (type) {
case UNLOCK:
handleUnlockReward();
break;
case COMPLETE:
if (thing.equals(ACHIEVEMENT)) {
Achievement achievement = Achievement.findById(thingId);
achievement.setCompleted(true);
achievement.giveReward();
}
break;
}
}
public double getAmount() {
return amount;
}
}