package mhfc.net.common.core.builders;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import mhfc.net.MHFCMain;
import mhfc.net.common.core.data.QuestDescriptionRegistry;
import mhfc.net.common.core.data.QuestDescriptionRegistry.QuestGroupData;
import mhfc.net.common.core.registry.MHFCQuestBuildRegistry;
import mhfc.net.common.network.serialization.GoalSerializer;
import mhfc.net.common.network.serialization.QuestSerializer;
import mhfc.net.common.quests.api.GoalDefinition;
import mhfc.net.common.quests.api.GoalReference;
import mhfc.net.common.quests.api.GoalReference.GoalRefSerializer;
import mhfc.net.common.quests.api.QuestDefinition;
public class BuilderJsonToQuests {
public static final ParameterizedType typeOfMapGoal = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { String.class, GoalDefinition.class };
}
@Override
public Type getRawType() {
return Map.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
public static final ParameterizedType typeOfMapQuest = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { String.class, QuestDefinition.class };
}
@Override
public Type getRawType() {
return Map.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
public static final ParameterizedType typeOfGroupMap = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { String.class, new ParameterizedType() {
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[] { String.class };
}
} };
}
@Override
public Type getRawType() {
return Map.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
public static final ParameterizedType typeOfGroupList = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { String.class };
}
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
public static final class GroupMappingType {
@SerializedName(MHFCQuestBuildRegistry.KEY_ORDERED_GROUPS)
public List<String> orderedGroups = new ArrayList<>();
@SerializedName(MHFCQuestBuildRegistry.KEY_GROUP_MAPPING)
public Map<String, List<String>> mapping = new HashMap<>();
}
public final static Gson gsonInstance = new GsonBuilder()
.registerTypeAdapter(GoalDefinition.class, new GoalSerializer())
.registerTypeAdapter(QuestDefinition.class, new QuestSerializer())
.registerTypeAdapter(GoalReference.class, new GoalRefSerializer()).serializeNulls().create();
private QuestDescriptionRegistry dataObject;
public BuilderJsonToQuests(QuestDescriptionRegistry dataObject) {
this.dataObject = dataObject;
}
public void acceptGoalsFrom(BufferedReader reader) throws IOException {
acceptGoalsFrom(new JsonReader(reader));
}
public void acceptGoalsFrom(JsonReader jsonReader) {
@SuppressWarnings("unchecked")
Map<String, GoalDefinition> map = (Map<String, GoalDefinition>) gsonInstance
.fromJson(jsonReader, typeOfMapGoal);
acceptGoals(map);
}
public void acceptGoals(JsonObject jsonInstance) {
@SuppressWarnings("unchecked")
Map<String, GoalDefinition> map = (Map<String, GoalDefinition>) gsonInstance
.fromJson(jsonInstance, typeOfMapGoal);
acceptGoals(map);
}
private void acceptGoals(Map<String, GoalDefinition> map) {
if (map == null) {
return;
}
dataObject.fillGoalDescriptions(map);
}
public void acceptGroupMappingFrom(BufferedReader reader) {
JsonReader jsonReader = new JsonReader(reader);
jsonReader.setLenient(true);
acceptGroupMappingFrom(jsonReader);
}
public void acceptGroupMappingFrom(JsonReader reader) {
GroupMappingType groupMapping = gsonInstance.fromJson(reader, GroupMappingType.class);
acceptGroupMapping(groupMapping);
}
public void acceptGroupMapping(JsonObject jsonObject) {
GroupMappingType groupMapping = gsonInstance.fromJson(jsonObject, GroupMappingType.class);
acceptGroupMapping(groupMapping);
}
private void acceptGroupMapping(GroupMappingType groupMapping) {
if (groupMapping == null) {
return;
}
List<String> orderedGroups = groupMapping.orderedGroups;
Map<String, List<String>> map = groupMapping.mapping;
if (!orderedGroups.containsAll(map.keySet())) {
MHFCMain.logger().warn(
"Detected quest groups which were not included in the ordering. These will appear last in an undefined order. Maybe you are missing the attribute "
+ MHFCQuestBuildRegistry.KEY_ORDERED_GROUPS);
}
if (!map.keySet().containsAll(orderedGroups)) {
MHFCMain.logger().warn(
"Detected ordering for quest groups without quests. These will appear empty. Maybe you are missing the attribute "
+ MHFCQuestBuildRegistry.KEY_GROUP_MAPPING);
}
QuestGroupData groupData = new QuestGroupData();
for (String key : map.keySet()) {
groupData.addQuestsToGroup(key, map.get(key));
}
groupData.orderGroups(orderedGroups);
dataObject.addGroups(groupData);
}
public void acceptQuestsFrom(BufferedReader reader) throws IOException {
acceptQuestsFrom(new JsonReader(reader));
}
public void acceptQuestsFrom(JsonReader reader) {
Map<String, QuestDefinition> map = gsonInstance.fromJson(reader, typeOfMapQuest);
acceptQuests(map);
}
public void acceptQuests(JsonObject jsonObject) {
Map<String, QuestDefinition> map = gsonInstance.fromJson(jsonObject, typeOfMapQuest);
acceptQuests(map);
}
private void acceptQuests(Map<String, QuestDefinition> map) {
if (map == null) {
return;
}
if (map.containsKey("")) {
throw new java.util.InputMismatchException("[MHFC] Quest identifier can not be an empty string");
}
dataObject.fillQuestDescriptions(map);
}
public JsonElement retrieveGoalsAsJson() {
return gsonInstance.toJsonTree(dataObject.getFullGoalDescriptionMap(), typeOfMapGoal);
}
public JsonElement retrieveQuestsAsJson() {
return gsonInstance.toJsonTree(dataObject.getFullQuestDescriptionMap(), typeOfMapQuest);
}
public JsonElement retrieveGroupsAsJson() {
JsonObject holder = new JsonObject();
JsonElement groupsInOrder = gsonInstance.toJsonTree(dataObject.getGroupsInOrder(), typeOfGroupList);
JsonElement groupMap = gsonInstance.toJsonTree(dataObject.getFullGroupMap(), typeOfGroupMap);
holder.add(MHFCQuestBuildRegistry.KEY_ORDERED_GROUPS, groupsInOrder);
holder.add(MHFCQuestBuildRegistry.KEY_GROUP_MAPPING, groupMap);
return holder;
}
}