package com.galvarez.ttw.model;
import static java.util.Arrays.asList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.annotations.Wire;
import com.artemis.systems.VoidEntitySystem;
import com.galvarez.ttw.model.components.AIControlled;
import com.galvarez.ttw.model.components.ArmyCommand;
import com.galvarez.ttw.model.components.Destination;
import com.galvarez.ttw.model.components.Diplomacy;
import com.galvarez.ttw.model.components.Discoveries;
import com.galvarez.ttw.model.components.InfluenceSource;
import com.galvarez.ttw.model.data.Discovery;
import com.galvarez.ttw.model.map.Terrain;
import com.galvarez.ttw.rendering.IconsSystem.Type;
import com.galvarez.ttw.rendering.NotificationsSystem;
import com.galvarez.ttw.rendering.components.Description;
import com.galvarez.ttw.rendering.components.Name;
import com.galvarez.ttw.screens.overworld.OverworldScreen;
/**
* Contains 'special discoveries', having special effects not covered by
* {@link EffectsSystem}.
*
* @author Guillaume Alvarez
*/
@Wire
public final class SpecialDiscoveriesSystem extends VoidEntitySystem {
private static final Logger log = LoggerFactory.getLogger(SpecialDiscoveriesSystem.class);
private static final String VILLAGE = "Village";
private static final String CITY = "City";
private static final String RAFT = "Raft";
private static final String BOAT = "Boat";
private ComponentMapper<Name> names;
private ComponentMapper<Description> descriptions;
private ComponentMapper<InfluenceSource> sources;
private ComponentMapper<Destination> destinations;
private ComponentMapper<ArmyCommand> commanders;
private ComponentMapper<Diplomacy> relations;
private ComponentMapper<AIControlled> ai;
private NotificationsSystem notifications;
private interface Special {
void apply(Entity empire, Discovery d, Discoveries discoveries);
}
private final Map<String, Special> effects = new HashMap<>();
private final OverworldScreen screen;
public SpecialDiscoveriesSystem(OverworldScreen screen) {
this.screen = screen;
effects.put(VILLAGE, new Special() {
@Override
public void apply(Entity empire, Discovery d, Discoveries discoveries) {
if (!discoveries.done.contains(CITY)) {
String name = names.get(empire).name;
String desc = "Village of " + name;
setDescription(empire, name, desc);
cannotMove(empire);
}
}
});
effects.put(CITY, new Special() {
@Override
public void apply(Entity empire, Discovery d, Discoveries discoveries) {
String name = names.get(empire).name;
String desc = "City of " + name;
setDescription(empire, name, desc);
cannotMove(empire);
}
});
effects.put(RAFT, new Special() {
@Override
public void apply(Entity empire, Discovery d, Discoveries discoveries) {
for (Entity army : sources.get(empire).secondarySources)
destinations.get(army).forbiddenTiles.add(Terrain.SHALLOW_WATER);
commanders.get(empire).forbiddenTiles.add(Terrain.SHALLOW_WATER);
}
});
effects.put(BOAT, new Special() {
@Override
public void apply(Entity empire, Discovery d, Discoveries discoveries) {
List<Terrain> list = asList(Terrain.DEEP_WATER, Terrain.SHALLOW_WATER);
for (Entity army : sources.get(empire).secondarySources)
destinations.get(army).forbiddenTiles.addAll(list);
commanders.get(empire).forbiddenTiles.addAll(list);
}
});
}
@Override
protected void processSystem() {
// nothing to do, called by other systems to activate special effects
}
private void setDescription(Entity empire, String name, String desc) {
descriptions.get(empire).desc = desc;
log.info("{} is now known as '{}'", name, desc);
// notify only player empire, avoid spamming
if (!ai.has(empire) || relations.get(empire).hasRelationWith(screen.player))
notifications.addNotification(() -> screen.select(empire, false), null, Type.BUILDINGS,
"%s is now known as '%s'", name, desc);
}
private void cannotMove(Entity capital) {
capital.edit().remove(Destination.class);
}
public void checkDiscoveries(Map<String, Discovery> discoveries) {
for (String d : effects.keySet())
if (!discoveries.containsKey(d))
log.warn("Cannot find discovery '{}' that has a special effect.", d);
}
public void apply(Entity empire, Discovery d, Discoveries discoveries) {
Special effect = effects.get(d.name);
if (effect != null)
effect.apply(empire, d, discoveries);
}
}