package com.github.czyzby.lml.parser.impl.tag.macro;
import com.badlogic.gdx.utils.ObjectMap;
import com.github.czyzby.kiwi.util.common.Strings;
import com.github.czyzby.kiwi.util.gdx.collection.GdxArrays;
import com.github.czyzby.lml.parser.LmlParser;
import com.github.czyzby.lml.parser.impl.tag.macro.util.Equation;
import com.github.czyzby.lml.parser.tag.LmlTag;
/** Repeats its data between tags until its condition evaluates to true. Uses the same equation system as
* {@link CalculationLmlMacroTag} and {@link ConditionalLmlMacroTag}. HAS to have attributes - its attributes are merged
* into a single equation. For example:
*
* <blockquote>
*
* <pre>
* <:while 9 < $someAction>
* <label>Label: {while:index}</label>
* </:while>
* </pre>
*
* </blockquote>This macro would create labels until "someAction" result is greater than 9 (or longer than 9, in case
* its a string).
*
* <p>
* Be careful: arguments are parsed BEFORE the macro is evaluated, NOT each time. This would enter an endless loop:
*
* <blockquote>
*
* <pre>
* <:assign myArg 12 />
* <:while 9<{myArg}>
* <label>Label: {while:index}</label>
* <:calculate myArg --{myArg}/>
* </:while>
* </pre>
*
* </blockquote>Even though "myArg" attribute would be decremented on each run, loop will never end, as it will be
* parsed to this before it is even running:
*
* <blockquote>
*
* <pre>
* <:while 9<12>
* <label>Label: {while:index}</label>
* <:calculate myArg --{myArg}/>
* </:while>
* </pre>
*
* </blockquote>
*
* <p>
* Note that this macro can be also used with named attributes:<blockquote>
*
* <pre>
* <:while test="9 < $someAction">
* <label>Label: {while:index}</label>
* </:while>
* </pre>
*
* </blockquote>
*
* @author MJ */
public class WhileLmlMacroTag extends AbstractLoopLmlMacroTag {
private final Equation equationParser;
private final String equation;
private int currentIndex;
public WhileLmlMacroTag(final LmlParser parser, final LmlTag parentTag, final StringBuilder rawTagData) {
super(parser, parentTag, rawTagData);
equation = getEquation();
equationParser = getEquationParser();
}
private String getEquation() {
if (GdxArrays.isEmpty(getAttributes())) {
getParser().throwErrorIfStrict(
"While macro needs tag attributes to determine condition. Found no attributes on tag: "
+ getTagName());
return null;
} else if (hasAttribute(AbstractConditionalLmlMacroTag.TEST_ATTRIBUTE)) {
return getAttribute(AbstractConditionalLmlMacroTag.TEST_ATTRIBUTE);
}
return convertAttributesToEquation();
}
private Equation getEquationParser() {
if (Strings.isNotBlank(equation)) {
return new Equation(getParser(), getActor());
}
return null;
}
@Override
protected boolean hasNext() {
return equationParser == null ? false : equationParser.getBooleanResult(equation);
}
@Override
protected int getIndex() {
return currentIndex;
}
@Override
protected void next(final ObjectMap<String, String> arguments) {
// While macro does not replace any local arguments.
currentIndex++;
}
@Override
public String[] getExpectedAttributes() {
return new String[] { AbstractConditionalLmlMacroTag.TEST_ATTRIBUTE };
}
}