package fr.lyrgard.hexScape.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.TreeMap;
import org.apache.commons.lang.StringUtils;
import fr.lyrgard.hexScape.bus.CoreMessageBus;
import fr.lyrgard.hexScape.message.ErrorMessage;
import fr.lyrgard.hexScape.model.CurrentUserInfo;
import fr.lyrgard.hexScape.model.card.CardInstance;
import fr.lyrgard.hexScape.model.game.Game;
import fr.lyrgard.hexScape.model.marker.HiddenMarkerDefinition;
import fr.lyrgard.hexScape.model.marker.HiddenMarkerInstance;
import fr.lyrgard.hexScape.model.marker.MarkerDefinition;
import fr.lyrgard.hexScape.model.marker.MarkerInstance;
import fr.lyrgard.hexScape.model.marker.MarkerType;
import fr.lyrgard.hexScape.model.marker.RevealableMarkerDefinition;
import fr.lyrgard.hexScape.model.marker.RevealableMarkerInstance;
import fr.lyrgard.hexScape.model.marker.StackableMarkerInstance;
import fr.lyrgard.hexScape.model.marker.UnknownTypeMarkerInstance;
import fr.lyrgard.hexScape.model.player.Player;
public class MarkerService {
public static synchronized MarkerService getInstance() {
if (INSTANCE == null) {
INSTANCE = new MarkerService();
}
return INSTANCE;
}
private static final String MARKERS_FOLDER_NAME = "markers";
private static final String markerPropertiesFilename = "marker.properties";
private static final String markerIconFilename = "icon.png";
private static final String NAME = "name";
private static final String TYPE = "type";
private static final String POSSIBLE_MARKERS_HIDDEN = "possibleMarkersHidden";
private static final String CAN_BE_PLACED_REVEALED = "canBePlacedRevealed";
private static MarkerService INSTANCE;
private MarkerService() {
getMarkersListForCard();
}
private Map<String, MarkerDefinition> markersByIds;
private List<File> getMarkerFolders() {
List<File> folders = new ArrayList<File>();
File commonFolder = new File(AssetService.COMMON_ASSET_FOLDER, MARKERS_FOLDER_NAME);
File gameFolder = new File(new File(AssetService.ASSET_FOLDER, ConfigurationService.getInstance().getGameFolder()), MARKERS_FOLDER_NAME);
folders.add(commonFolder);
folders.add(gameFolder);
return folders;
}
public Collection<MarkerDefinition> getMarkersListForCard() {
if (markersByIds != null) {
return markersByIds.values();
}
markersByIds = new TreeMap<>();
Map<String, String[]> hiddenMarkerTempCollection = new HashMap<>();
for (File baseFolder : getMarkerFolders()) {
if (baseFolder.exists()) {
markerDefinition: for (File folder : baseFolder.listFiles()) {
if (folder.exists() && folder.isDirectory()) {
File markerPropertiesFile = new File(folder, markerPropertiesFilename);
if (markerPropertiesFile.exists() && markerPropertiesFile.isFile() && markerPropertiesFile.canRead()) {
Properties markerProperties = new Properties();
InputStream input;
try {
input = new FileInputStream(markerPropertiesFile);
markerProperties.load(input);
MarkerDefinition marker = null;
String id = folder.getName();
String name = markerProperties.getProperty(NAME);
File iconFile = new File(folder, markerIconFilename);
if (!iconFile.exists() || !iconFile.isFile() || !iconFile.canRead() ) {
CoreMessageBus.post(new ErrorMessage(CurrentUserInfo.getInstance().getPlayerId(), "No icon.png file was found in " + markerPropertiesFile.getAbsolutePath() + " marker definition. This marker definition will be skiped"));
continue markerDefinition;
}
String typeString = markerProperties.getProperty(TYPE);
MarkerType type = null;
try {
type = MarkerType.valueOf(typeString);
} catch (IllegalArgumentException e) {
CoreMessageBus.post(new ErrorMessage(CurrentUserInfo.getInstance().getPlayerId(), "The marker type \"" + typeString + "\" in " + markerPropertiesFile.getAbsolutePath() + " is not a valid type. This marker definition will be skiped"));
continue markerDefinition;
}
switch (type) {
case NORMAL:
case STACKABLE:
marker = new MarkerDefinition();
break;
case REVEALABLE:
marker = new RevealableMarkerDefinition();
((RevealableMarkerDefinition)marker).setCanBePlacedRevealed(Boolean.TRUE.toString().equalsIgnoreCase(markerProperties.getProperty(CAN_BE_PLACED_REVEALED, Boolean.FALSE.toString())));
break;
case HIDDEN:
marker = new HiddenMarkerDefinition();
String possibleHiddenMarkersList = markerProperties.getProperty(POSSIBLE_MARKERS_HIDDEN);
if (possibleHiddenMarkersList != null) {
String[] array = possibleHiddenMarkersList.split(",");
hiddenMarkerTempCollection.put(id, array);
}
break;
}
marker.setId(id);
marker.setType(type);
marker.setName(name);
marker.setImage(iconFile);
markersByIds.put(marker.getId(), marker);
} catch (IOException e) {
CoreMessageBus.post(new ErrorMessage(CurrentUserInfo.getInstance().getPlayerId(), "Error reading file \"" + markerPropertiesFile.getAbsolutePath() + "\". This marker definition will be skiped"));
}
}
}
}
}
}
// process HiddenMarker now that all marker definition are loaded
for (Entry<String, String[]> entry : hiddenMarkerTempCollection.entrySet()) {
HiddenMarkerDefinition definition = (HiddenMarkerDefinition)markersByIds.get(entry.getKey());
for (String possibleMarkerId : entry.getValue()) {
MarkerDefinition possibleMarkerDefinition = markersByIds.get(StringUtils.trim(possibleMarkerId));
if (possibleMarkerDefinition != null && possibleMarkerDefinition instanceof RevealableMarkerDefinition) {
definition.getPossibleMarkersHidden().add((RevealableMarkerDefinition)possibleMarkerDefinition);
((RevealableMarkerDefinition)possibleMarkerDefinition).setHiddenMarkerDefinition(definition);
}
}
}
return markersByIds.values();
}
public void normalizeMarkers(Game game) {
if (game != null) {
for (Player player : game.getPlayers()) {
if (player != null && player.getArmy() != null) {
for (CardInstance card : player.getArmy().getCards()) {
if (card != null) {
List<MarkerInstance> newMarkers = new ArrayList<>();
Iterator<MarkerInstance> it = card.getMarkers().iterator();
while (it.hasNext()) {
MarkerInstance marker = it.next();
if (marker instanceof UnknownTypeMarkerInstance) {
MarkerInstance newMarker = getNewMarkerInstance(marker.getMarkerDefinitionId(), marker.getId(), ((UnknownTypeMarkerInstance) marker).getNumber(), ((UnknownTypeMarkerInstance) marker).getHiddenMarkerTypeId());
newMarkers.add(newMarker);
it.remove();
}
}
for (MarkerInstance marker : newMarkers) {
card.addMarker(marker);
}
}
}
}
}
}
}
public MarkerInstance getNewMarkerInstance(String markerTypeId, String id, int number, String hiddenMarkerTypeId) {
MarkerDefinition markerDefinition = MarkerService.getInstance().getMarkersByIds().get(markerTypeId);
if (markerDefinition == null) {
CoreMessageBus.post(new ErrorMessage(CurrentUserInfo.getInstance().getId(), "Unable to find marker type " + markerTypeId));
return null;
}
MarkerInstance marker = null;
switch (markerDefinition.getType()) {
case NORMAL:
marker = new MarkerInstance(markerDefinition.getId());
break;
case STACKABLE:
marker = new StackableMarkerInstance(markerDefinition.getId(), number);
break;
case REVEALABLE:
marker = new RevealableMarkerInstance(markerDefinition.getId());
break;
case HIDDEN:
marker = new HiddenMarkerInstance(markerDefinition.getId(), hiddenMarkerTypeId);
break;
}
marker.setId(id);
return marker;
}
public Map<String, MarkerDefinition> getMarkersByIds() {
return markersByIds;
}
}