package toadmess.explosives.config;
import static toadmess.explosives.config.ConfProps.CONF_DEBUGCONFIG;
import static toadmess.explosives.config.ConfProps.CONF_ENTITIES;
import static toadmess.explosives.config.ConfProps.CONF_WORLDS;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.util.config.Configuration;
import toadmess.explosives.config.entity.EntityConf;
import toadmess.explosives.config.entity.EntityConfReader;
/**
* Contains all of the different EntityConf instances for all worlds and all entities.
* It is used to procure a relevant configuration for a specific event.
*
* @author John Revill
*/
public class MultiWorldConfStore {
/**
* Maps the entity type to a map. The returned map maps the world name to the config to use.
*/
private final Map<Class<? extends Entity>, Map<String, EntityConf>> worldConfs = new HashMap<Class<? extends Entity>, Map<String, EntityConf>>();
/**
* This is the name used to reference the default world.
* Used to key into the map of ExplodingConf to get the default world config
*/
public static final String DEF_WORLD_NAME = "";
public final Logger log;
public MultiWorldConfStore(final Logger log) {
this.log = log;
}
public void readConfsForEntity(final Class<? extends Entity> entityType, final Configuration conf) {
// Get the unqualified class name of the entity. This is used for looking it up in the configuration.
final String entityName = entityType.getName().substring(entityType.getName().lastIndexOf('.')+1);
final String confEntityPath = CONF_ENTITIES + "." + entityName;
final boolean isDebugConf = conf.getBoolean(CONF_DEBUGCONFIG.toString(), false);
final EntityConf defWorldConfig = new EntityConfReader(conf, confEntityPath, log).readEntityConf();
this.add(defWorldConfig, entityType, MultiWorldConfStore.DEF_WORLD_NAME);
if(isDebugConf) {
if(defWorldConfig.isEmptyConfig()) {
log.info("HigherExplosives: There is no default config for " + entityName + ". Those explosions will be left unaffected unless they have a world specific configuration.");
} else {
log.info("HigherExplosives: Default config for " + entityName + " is:\n" + defWorldConfig);
}
}
final List<String> worldNames = conf.getKeys(CONF_WORLDS.toString());
if(null != worldNames) {
for(final String worldName : worldNames) {
final String worldEntityPath = CONF_WORLDS + "." + worldName + "." + confEntityPath;
if(null != conf.getProperty(worldEntityPath)) {
final EntityConf worldConf = new EntityConfReader(conf, worldEntityPath, this.log).readEntityConf();
this.add(worldConf, entityType, worldName);
if(isDebugConf) {
if(!worldConf.isEmptyConfig()) {
this.log.info("HigherExplosives: World \"" + worldName + "\" config for " + entityName + " is " + worldConf);
}
}
}
}
}
}
private void add(final EntityConf conf, final Class<? extends Entity> entityClass, final String worldName) {
final Map<String, EntityConf> worldConfMap;
if(this.worldConfs.containsKey(entityClass)) {
worldConfMap = this.worldConfs.get(entityClass);
} else {
worldConfMap = new HashMap<String, EntityConf>();
}
worldConfMap.put(worldName, conf);
worldConfs.put(entityClass, worldConfMap);
}
/**
* Gets an active config (within the active bounds) for the given entity type at the given world location.
*
* @param entityType
* @param location
*
* @return Null if there is no active configuration at the given location for the given type.
*/
public EntityConf getActiveConf(final Class<? extends Entity> entityType, final Location location) {
if(null == location) {
return null;
}
final String worldName = location.getWorld().getName();
final Map<String, EntityConf> worldConfMap = this.worldConfs.get(entityType);
final EntityConf ec;
ec = worldConfMap.get(worldConfMap.containsKey(worldName) ? worldName : DEF_WORLD_NAME);
if(ec.getActiveBounds().isWithinBounds(location)) {
return ec;
}
return null;
}
public Set<EntityConf> allConfigsAndSubConfigs() {
final Set<EntityConf> allConfigs = new HashSet<EntityConf>();
for(final Map<String, EntityConf> worldConfMap : this.worldConfs.values()) {
final List<EntityConf> thisWorldsConfs = new ArrayList<EntityConf>();
thisWorldsConfs.addAll(worldConfMap.values());
thisWorldsConfs.add(worldConfMap.get(DEF_WORLD_NAME));
for(final EntityConf rootConfig : thisWorldsConfs) {
allConfigs.addAll(rootConfig.getConfigAndAllSubConfigs());
}
}
return Collections.unmodifiableSet(allConfigs);
}
}