package tc.oc.pgm.eventrules;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Splitter;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.util.Vector;
import org.jdom2.Attribute;
import org.jdom2.Element;
import tc.oc.api.docs.SemanticVersion;
import tc.oc.pgm.filters.Filter;
import tc.oc.pgm.filters.operator.ChainFilter;
import tc.oc.pgm.filters.parser.FilterParser;
import tc.oc.pgm.kits.KitParser;
import tc.oc.pgm.kits.RemovableValidation;
import tc.oc.pgm.map.MapModuleContext;
import tc.oc.pgm.map.ProtoVersions;
import tc.oc.pgm.regions.EverywhereRegion;
import tc.oc.pgm.regions.Region;
import tc.oc.pgm.regions.RegionParser;
import tc.oc.pgm.utils.XMLUtils;
import tc.oc.pgm.xml.InvalidXMLException;
import tc.oc.pgm.xml.Node;
import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowConsumer;
public class EventRuleParser {
private final MapModuleContext context;
private final FilterParser filterParser;
private final RegionParser regionParser;
private final KitParser kitParser;
private final EventRuleContext ruleContext;
private final SemanticVersion proto;
public EventRuleParser(MapModuleContext context, EventRuleContext ruleContext) {
this.context = context;
this.ruleContext = ruleContext;
this.filterParser = context.needModule(FilterParser.class);
this.regionParser = context.needModule(RegionParser.class);
this.kitParser = context.needModule(KitParser.class);
this.proto = context.getProto();
}
private boolean useId() {
return proto.isNoOlderThan(ProtoVersions.FILTER_FEATURES);
}
private void add(Element el, EventRule rule) throws InvalidXMLException {
ruleContext.add(context.features().define(el, EventRule.class, rule));
}
public void parse(Element el) throws InvalidXMLException {
final Region region;
if(useId()) {
// Multiple regions are unioned, but the default is NOT an empty union
region = regionParser.property(el).optionalUnion(EverywhereRegion.INSTANCE);
} else {
region = regionParser.parseReferenceAndChildUnion(el);
}
BaseComponent message = XMLUtils.parseFormattedText(el, "message");
boolean earlyWarning = XMLUtils.parseBoolean(el.getAttribute("early-warning"), false);
Filter effectFilter = filterParser.parseOptionalProperty(el, "filter").orElse(null);
kitParser.property(el, "kit").optional().ifPresent(rethrowConsumer(
kit -> add(el, EventRule.newKitRegion(EventRuleScope.EFFECT, region, effectFilter, kit, false))
));
kitParser.property(el, "lend-kit").validate(RemovableValidation.get()).optional().ifPresent(rethrowConsumer(
kit -> add(el, EventRule.newKitRegion(EventRuleScope.EFFECT, region, effectFilter, kit, true))
));
Attribute attrVelocity = el.getAttribute("velocity");
if(attrVelocity != null) {
// Legacy support
String velocityText = attrVelocity.getValue();
if(velocityText.charAt(0) == '@') velocityText = velocityText.substring(1);
Vector velocity = XMLUtils.parseVector(attrVelocity, velocityText);
add(el, EventRule.newVelocityRegion(EventRuleScope.EFFECT, region, effectFilter, velocity));
}
for(String tag : EventRuleScope.byTag.keySet()) {
Filter filter;
if(useId()) {
filter = filterParser.parseOptionalProperty(el, tag).orElse(null);
} else {
// Legacy syntax allows a list of filter names in the attribute
Node node = Node.fromAttr(el, tag);
if(node == null) {
filter = null;
} else {
List<Filter> filters = new ArrayList<>();
for(String name : Splitter.on(" ").split(node.getValue())) {
filters.add(filterParser.parseReference(node, name));
}
switch(filters.size()) {
case 0: filter = null; break;
case 1: filter = filters.get(0); break;
default: filter = ChainFilter.reverse(filters);
}
}
}
if(filter != null) {
for(EventRuleScope scope : EventRuleScope.byTag.get(tag)) {
add(el, EventRule.newEventFilter(scope, region, filter, message, earlyWarning));
}
}
}
}
}