package net.gnehzr.tnoodle.server.webscrambles;
import static net.gnehzr.tnoodle.utils.GsonUtils.GSON;
import static net.gnehzr.tnoodle.utils.GwtSafeUtils.azzert;
import static net.gnehzr.tnoodle.utils.GwtSafeUtils.parseExtension;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.gnehzr.tnoodle.scrambles.Puzzle;
import net.gnehzr.tnoodle.scrambles.PuzzlePlugins;
import net.gnehzr.tnoodle.server.SafeHttpServlet;
import net.gnehzr.tnoodle.utils.LazyInstantiator;
import net.gnehzr.tnoodle.utils.LazyInstantiatorException;
import net.gnehzr.tnoodle.utils.BadLazyClassDescriptionException;
@SuppressWarnings("serial")
public class PuzzleListHandler extends SafeHttpServlet {
private final Map<String, Map<String, Object>> puzzleInfoByShortName;
private final List<Map<String, Object>> puzzleInfos;
private final String puzzleInfosJSON;
public PuzzleListHandler() throws IOException, BadLazyClassDescriptionException {
SortedMap<String, LazyInstantiator<Puzzle>> scramblers = PuzzlePlugins.getScramblers();
ArrayList<Map<String, Object>> puzzleInfos_ = new ArrayList<Map<String, Object>>(scramblers.size());
HashMap<String, Map<String, Object>> puzzleInfoByShortName_ = new HashMap<String, Map<String, Object>>(scramblers.size());
for(Entry<String, LazyInstantiator<Puzzle>> scrambler : scramblers.entrySet()) {
String shortName = scrambler.getKey();
String longName = PuzzlePlugins.getScramblerLongName(shortName);
Map<String, Object> puzzleInfo = new HashMap<String, Object>();
puzzleInfo.put("shortName", shortName);
puzzleInfo.put("longName", longName);
puzzleInfo = Collections.unmodifiableMap(puzzleInfo);
puzzleInfos_.add(puzzleInfo);
puzzleInfoByShortName_.put(shortName, puzzleInfo);
}
puzzleInfos = Collections.unmodifiableList(puzzleInfos_);
puzzleInfoByShortName = Collections.unmodifiableMap(puzzleInfoByShortName_);
puzzleInfosJSON = GSON.toJson(puzzleInfos);
}
private Map<String, Object> getPuzzleInfo(LazyInstantiator<Puzzle> lazyScrambler, boolean includeStatus) throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, MalformedURLException, BadLazyClassDescriptionException, LazyInstantiatorException {
Puzzle scrambler = lazyScrambler.cachedInstance();
Map<String, Object> info = puzzleInfoByShortName.get(scrambler.getShortName());
azzert(info != null);
// info is unmodifiable, so we copy it
info = new HashMap<String, Object>(info);
if(includeStatus) {
info.put("initializationStatus", scrambler.getInitializationStatus());
}
return info;
}
@Override
protected void wrappedService(HttpServletRequest request, HttpServletResponse response, String[] path, LinkedHashMap<String, String> query) throws IOException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException, BadLazyClassDescriptionException, LazyInstantiatorException {
boolean includeStatus = query.get("includeStatus") != null;
if(path.length == 0) {
sendError(request, response, "Please specify an extension (and optionally, a puzzle)");
} else {
String[] puzzle_extension = parseExtension(path[0]);
String puzzle = puzzle_extension[0];
String extension = puzzle_extension[1];
if (extension == null) {
sendError(request, response, "Please specify an extension");
return;
}
SortedMap<String, LazyInstantiator<Puzzle>> scramblers = PuzzlePlugins.getScramblers();
if(extension.equals("json")) {
if(puzzle.equals("")) {
if(includeStatus) {
ArrayList<Map<String, Object>> puzzleInfosWithStatus = new ArrayList<Map<String, Object>>();
for(Map<String, Object> puzzleInfo : puzzleInfos) {
LazyInstantiator<Puzzle> lazyScrambler = scramblers.get(puzzleInfo.get("shortName"));
azzert(lazyScrambler != null);
puzzleInfosWithStatus.add(getPuzzleInfo(lazyScrambler, includeStatus));
}
sendJSON(request, response, GSON.toJson(puzzleInfosWithStatus));
} else {
sendJSON(request, response, puzzleInfosJSON);
}
} else {
LazyInstantiator<Puzzle> lazyScrambler = scramblers.get(puzzle);
if (lazyScrambler == null) {
sendError(request, response, "Invalid scrambler: " + puzzle);
return;
}
Map<String, Object> puzzleInfo = getPuzzleInfo(lazyScrambler, includeStatus);
String puzzleInfoJSON = GSON.toJson(puzzleInfo);
sendJSON(request, response, puzzleInfoJSON);
}
} else {
sendError(request, response, "Invalid extension: " + extension);
}
}
}
}