package net.t7seven7t.craftfx.effect;
import com.google.common.collect.ImmutableList;
import net.t7seven7t.craftfx.data.ConfigData;
import net.t7seven7t.craftfx.data.Data;
import net.t7seven7t.craftfx.data.effect.DelayData;
import net.t7seven7t.craftfx.data.effect.ExtentData;
import net.t7seven7t.craftfx.data.effect.TargetSelectorData;
import net.t7seven7t.craftfx.data.effect.TimerData;
import org.bukkit.configuration.ConfigurationSection;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
/**
*
*/
public final class EffectSpec {
private static final List<Data> DEFAULT_DATA = new ArrayList<>();
static {
DEFAULT_DATA.add(new ConfigData());
DEFAULT_DATA.add(new ExtentData());
DEFAULT_DATA.add(new DelayData(0));
DEFAULT_DATA.add(new TimerData());
DEFAULT_DATA.add(new TargetSelectorData("self", 1, 5));
}
private final List<String> aliases = new ArrayList<>();
private final List<Data> dataList = new ArrayList<>();
final Map<ExtentState, Consumer<EffectContext>> consumerMap = new IdentityHashMap<>(2);
private EffectSpec() {
}
public static void addDefaultData(Data data) {
DEFAULT_DATA.add(data);
}
public static Builder builder() {
return new Builder();
}
public Effect newEffect(ConfigurationSection config) {
final Effect effect = new Effect(config, consumerMap);
DEFAULT_DATA.forEach(d -> effect.offer(d.copy()));
dataList.forEach(d -> effect.offer(d.copy()));
return effect;
}
public List<String> getAliases() {
return ImmutableList.copyOf(aliases);
}
public static final class Builder {
private final EffectSpec spec;
public Builder() {
this.spec = new EffectSpec();
}
public Builder aliases(String... aliases) {
for (String alias : aliases) {
spec.aliases.add(alias.toLowerCase());
}
return Builder.this;
}
public Builder data(Data data) {
Iterator<Data> it = spec.dataList.iterator();
Class<?> clazz = data.getClass();
while (it.hasNext()) {
if (it.next().getClass() == clazz) it.remove();
}
spec.dataList.add(data);
return Builder.this;
}
/**
* Adds an effect to be run at the specified extent state. Only one consumer allowed per
* state. Additional will overwrite previous.
*
* @param state state to run the effect at
* @param consumer the method that runs the effect
* @return the same builder object
*/
public Builder effect(ExtentState state, Consumer<EffectContext> consumer) {
spec.consumerMap.put(state, consumer);
return Builder.this;
}
/**
* Fills all extent states with the consumer to run.
*
* @param consumer the method that runs the effect
* @return the same builder object
*/
public Builder effect(Consumer<EffectContext> consumer) {
spec.consumerMap.put(ExtentState.START, consumer);
spec.consumerMap.put(ExtentState.END, consumer);
return Builder.this;
}
public EffectSpec build() {
return spec;
}
}
}