/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.brooklyn.core.workflow.steps.variables;

import com.google.common.reflect.TypeToken;
import freemarker.core.ParseException;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
import org.apache.brooklyn.core.workflow.WorkflowExpressionResolution;
import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
import org.apache.brooklyn.util.collections.*;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.predicates.DslPredicates;
import org.apache.brooklyn.util.core.text.TemplateProcessor;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.text.QuotedStringTokenizer;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Timestamp;
import org.apache.commons.lang3.tuple.MutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.time.Instant;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

public class SetVariableWorkflowStep extends WorkflowStepDefinition {

    private static final Logger log = LoggerFactory.getLogger(SetVariableWorkflowStep.class);

    public static final String SHORTHAND =
            "[ [ ${variable.type} ] ${variable.name} [ \"=\" ${value...} ] ]";

    public static final ConfigKey<TypedValueToSet> VARIABLE = ConfigKeys.newConfigKey(TypedValueToSet.class, "variable");
    public static final ConfigKey<Object> VALUE = ConfigKeys.newConfigKey(Object.class, "value");

    public enum InterpolationMode {
        WORDS,
        DISABLED,
        FULL,
    }
    public static final ConfigKey<InterpolationMode> INTERPOLATION_MODE = ConfigKeys.newConfigKey(InterpolationMode.class, "interpolation_mode",
            "Whether interpolation runs on the full value (not touching quotes; the default in most places), " +
                    "on words (if unquoted, unquoting others; the default for 'let var = value' shorthand), " +
                    "or is disabled (not applied at all)");
    public static final ConfigKey<TemplateProcessor.InterpolationErrorMode> INTERPOLATION_ERRORS = ConfigKeys.newConfigKey(TemplateProcessor.InterpolationErrorMode.class, "interpolation_errors",
            "Whether unresolvable interpolated expressions fail and return an error (the default for 'let'), " +
                    "ignore the expression leaving it in place (the default for 'load'), " +
                    "or replace the expression with a blank string");

    @Override
    public void populateFromShorthand(String expression) {
        Map<String, Object> newInput = populateFromShorthandTemplate(SHORTHAND, expression, true, true);
        if (newInput.get(VALUE.getName())!=null && input.get(INTERPOLATION_MODE.getName())==null) {
            setInput(INTERPOLATION_MODE, InterpolationMode.WORDS);
        }
    }

    @Override
    public void validateStep(@Nullable ManagementContext mgmt, @Nullable WorkflowExecutionContext workflow) {
        super.validateStep(mgmt, workflow);

        if (input.get(VARIABLE.getName())==null) {
            throw new IllegalArgumentException("Variable name is required");
        }
        if (input.get(VALUE.getName())==null) {
            throw new IllegalArgumentException("Value is required");
        }
    }

    @Override
    protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
        TypedValueToSet variable = context.getInput(VARIABLE);
        if (variable ==null) throw new IllegalArgumentException("Variable name is required");
        String name = context.resolve(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_INPUT, variable.name, String.class);
        if (Strings.isBlank(name)) throw new IllegalArgumentException("Variable name is required");
        TypeToken<?> type = context.lookupType(variable.type, () -> null);

        Object unresolvedValue = input.get(VALUE.getName());

        Object resolvedValue = new ConfigurableInterpolationEvaluation(context, type, unresolvedValue, context.getInputOrDefault(INTERPOLATION_MODE), context.getInputOrDefault(INTERPOLATION_ERRORS)).evaluate();

        Object oldValue = setWorkflowScratchVariableDotSeparated(context, name, resolvedValue);
        // these are easily inferred from workflow vars
//        context.noteOtherMetadata("Value set", resolvedValue);
//        if (oldValue!=null) context.noteOtherMetadata("Previous value", oldValue);
        return context.getPreviousStepOutput();
    }

    static Object setWorkflowScratchVariableDotSeparated(WorkflowStepInstanceExecutionContext context, String name, Object resolvedValue) {
        Object oldValue;
        if (name.contains(".")) {
            String[] names = name.split("\\.");
            String names0 = names[0];
            if ("output".equals(names0)) throw new IllegalArgumentException("Cannot set subfield in output");  // catch common error
            Object h = context.getWorkflowExectionContext().getWorkflowScratchVariables().get(names0);
            if (!(h instanceof Map)) throw new IllegalArgumentException("Cannot set " + name + " because " + names0 + " is " + (h == null ? "unset" : "not a map"));
            for (int i = 1; i < names.length - 1; i++) {
                Object hi = ((Map<?, ?>) h).get(names[i]);
                if (hi == null) {
                    hi = MutableMap.of();
                    ((Map) h).put(names[i], hi);
                } else if (!(hi instanceof Map))
                    throw new IllegalArgumentException("Cannot set " + name + " because " + names[i] + " is not a map");
                h = hi;
            }
            oldValue = ((Map) h).put(names[names.length - 1], resolvedValue);
        } else if (name.contains("[")) {
            String[] names = name.split("((?<=\\[|\\])|(?=\\[|\\]))");
            if (names.length != 4 || !"[".equals(names[1]) || !"]".equals(names[3])) {
                throw new IllegalArgumentException("Invalid list index specifier " + name);
            }
            String listName = names[0];
            int listIndex = Integer.parseInt(names[2]);
            Object o = context.getWorkflowExectionContext().getWorkflowScratchVariables().get(listName);
            if (!(o instanceof List))
                throw new IllegalArgumentException("Cannot set " + name + " because " + listName + " is " + (o == null ? "unset" : "not a list"));

            List l = MutableList.copyOf(((List)o));
            if (listIndex < 0 || listIndex >= l.size()) {
                throw new IllegalArgumentException("Invalid list index " + listIndex);
            }
            oldValue = l.set(listIndex, resolvedValue);
            context.getWorkflowExectionContext().updateWorkflowScratchVariable(listName, l);
        } else {
            oldValue = context.getWorkflowExectionContext().updateWorkflowScratchVariable(name, resolvedValue);
        }
        return oldValue;
    }

    private enum LetMergeMode { NONE, SHALLOW, DEEP }

    public static class ConfigurableInterpolationEvaluation<T> {
        protected final WorkflowStepInstanceExecutionContext context;
        protected final TypeToken<T> type;
        protected final Object unresolvedValue;
        protected final InterpolationMode interpolationMode;
        protected final TemplateProcessor.InterpolationErrorMode errorMode;

        public ConfigurableInterpolationEvaluation(WorkflowStepInstanceExecutionContext context, TypeToken<T> type, Object unresolvedValue) {
            this(context, type, unresolvedValue, null, null);
        }
        public ConfigurableInterpolationEvaluation(WorkflowStepInstanceExecutionContext context, TypeToken<T> type, Object unresolvedValue, InterpolationMode interpolationMode, TemplateProcessor.InterpolationErrorMode errorMode) {
            this.context = context;
            this.unresolvedValue = unresolvedValue;
            this.type = type;
            this.interpolationMode = interpolationMode;
            this.errorMode = errorMode;
        }

        public boolean unquotedStartsWith(String s, char c) {
            if (s==null) return false;
            s = s.trim();
            s = Strings.removeFromStart(s, "\"");
            s = Strings.removeFromStart(s, "\'");
            s = s.trim();
            return (s.startsWith(""+c));
        }

        public boolean trimmedEndsWithQuote(String s) {
            if (s==null) return false;
            s = s.trim();
            return s.endsWith("\"") || s.endsWith("\'");
        }

        public Function<String,TypeToken<?>> ifUnquotedStartsWithThen(char c, Class<?> clazz) {
            return s -> (!unquotedStartsWith(s, c)) ? null : TypeToken.of(clazz);
        }

        public T evaluate() {
            try {
                Object result = unresolvedValue;

                Object resultCoerced;
                TypeToken<? extends Object> typeIntermediate = type == null ? TypeToken.of(Object.class) : type;

                if (interpolationMode == InterpolationMode.DISABLED) {
                    resultCoerced = context.getWorkflowExectionContext().resolveCoercingOnly(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_RUNNING, result, typeIntermediate);

                } else if (result instanceof String && interpolationMode == InterpolationMode.WORDS) {
                    result = process((String) result);
                    resultCoerced = context.getWorkflowExectionContext().resolveCoercingOnly(WorkflowExpressionResolution.WorkflowExpressionStage.STEP_RUNNING, result, typeIntermediate);

                } else {
                    // full, or null the default
                    resultCoerced = resolveSubPart(result, typeIntermediate);
                }

                return (T) resultCoerced;
            } catch (Exception e) {
                throw e;
            }
        }

        <T> T resolveSubPart(Object v, TypeToken<T> type) {
            return new WorkflowExpressionResolution(context.getWorkflowExectionContext(), WorkflowExpressionResolution.WorkflowExpressionStage.STEP_RUNNING, false, WorkflowExpressionResolution.WrappingMode.NONE, errorMode)
                    .resolveWithTemplates(v, type);
        }

        Object process(String input) {
            if (Strings.isBlank(input)) return input;

            List<String> wordsByQuote = null;
            try {
                // first deal with internal quotes
                QuotedStringTokenizer qst = qst(input);
                if (qst.isQuoted(input)) {
                    // special treatment if whole line is quoted
                    wordsByQuote = MutableList.of(input);
                } else {
                    wordsByQuote = qst.remainderAsList();
                }
                // then look for operators etc
                return process(wordsByQuote);
            } catch (Exception e) {
                Exceptions.propagateIfFatal(e);
                if (wordsByQuote==null || wordsByQuote.size()>1) {
                    if (Exceptions.getCausalChain(e).stream().anyMatch(cause -> cause instanceof ParseException || cause instanceof IllegalArgumentException)) {
                        // try again with the whole thing as tokens, if it is an interpolated string with spaces inside it or mismatched quotes
                        try {
                            return process(MutableList.of(input));
                        } catch (Exception e2) {
                            log.debug("Failed to process expression as tokens or as string; preferring error from former, but error from latter was: " + e2);
                        }
                    }
                }
                throw Exceptions.propagate(e);
            }
        }

        QuotedStringTokenizer qst(String input) {
            return QuotedStringTokenizer.builder().includeQuotes(true).includeDelimiters(true).expectQuotesDelimited(true).failOnOpenQuote(true).build(input);
        }

        Object process(List<String> w) {
            return process(w, false);
        }

        Object process(List<String> w, boolean ternaryColonAllowed) {
            // if no tokens, treat as null
            if (w.isEmpty()) return null;

            Maybe<Object> result;

            // Order of operations:
            // not used: () [] -> . :: (i.e. Function call, scope, array/member access)
            // not used: ! ~ - + & ++ -- (i.e. unary operators)

            // #__: ?: (i.e. ternary)
            result = handleTokenIfPresent(w, false,
                    ternaryColonAllowed ? MutableMap.of(
                        "?", this::handleTernaryCondition,
                        ":", this::handleTernaryArms)
                            : MutableMap.of("?", this::handleTernaryCondition)
            );
            if (result.isPresent()) return result.get();


            // ?: ?? (nullish - treat as an unary operator)
            result = handleTokenIfPresent(w, false, MutableMap.of("??", this::handleNullish));
            if (result.isPresent()) return result.get();
            //NOTE: levels 4 and 3 are out of order (by the C Order or operations)

            // #4: + -
            result = handleTokenIfPresent(w, true, MutableMap.of("+", this::handleAdd, "-", this::handleSubtract));
            if (result.isPresent()) return result.get();

            // #3: - * / % MOD
            result = handleTokenIfPresent(w, true, MutableMap.of("*", this::handleMultiply, "/", this::handleDivide));
            if (result.isPresent()) return result.get();
            result = handleTokenIfPresent(w, true, MutableMap.of("%", this::handleModulo));
            if (result.isPresent()) return result.get();

            // #5: << >> (i.e. bitwise shift left and right

            // #6: < <= > >=
            result = handleTokenIfPresent(w, false, MutableMap.of(
                    "==", this::handleEquals,
                    "<", this::handleOrderedLessThan,
                    "<=", this::handleOrderedLessThanOrEqual,
                    ">", this::handleOrderedGreaterThan,
                    ">=", this::handleOrderedGreaterThanOrEqual
            ));
            if (result.isPresent()) return result.get();

            // #7: == !=
            // #8: & (i.e. bitwise AND)
            // #9: ^ (i.e. bitwise XOR)
            // #10: | (i.e. bitwise OR)

            // #11: && (i.e. logical AND)
            result = handleTokenIfPresent(w, false, MutableMap.of("&&", this::handleBooleanAnd));
            if (result.isPresent()) return result.get();
            // #12: || (i.e. logical OR)
            result = handleTokenIfPresent(w, false, MutableMap.of("||", this::handleBooleanOr));
            if (result.isPresent()) return result.get();


            // #14: = += -= *= /= %= &= |= ^= <<= >>= (i.e. assignment operators)
            // #15: ,

            // tokens include space delimiters and are still quotes, so unwrap then just stitch together. will preserve spaces.
            boolean resolveToString = w.size()>1;
            QuotedStringTokenizer qst = qst("");
            List<Object> objs = w.stream().map(t -> {
                if (qst.isQuoted(t)) return qst.unwrapIfQuoted(t);
                TypeToken<?> target = resolveToString ? TypeToken.of(String.class) : TypeToken.of(Object.class);
                return resolveSubPart(t, target);
            }).collect(Collectors.toList());
            if (!resolveToString) return objs.get(0);
            return ((List<String>)(List)objs).stream().collect(Collectors.joining());
        }

        private Maybe<Object> handleTokenIfPresent(List<String> tokens, boolean startAtRight, Map<String, BiFunction<List<String>,List<String>,Object>> tokenProcessors) {
            for (int i0=0; i0<tokens.size(); i0++) {
                int i = startAtRight ? tokens.size()-1-i0 : i0;
                String t = tokens.get(i);
                BiFunction<List<String>, List<String>, Object> p = tokenProcessors.get(t);
                if (p!=null) {
                    List<String> lhs = trim(tokens.subList(0, i));
                    List<String> rhs = trim(tokens.subList(i + 1, tokens.size()));
                    return Maybe.of(p.apply(lhs, rhs));
                }
            }
            return Maybe.absent();
        }

        private List<String> trim(List<String> l) {
            if (!l.isEmpty() && Strings.isBlank(l.get(0))) l = l.subList(1, l.size());
            if (!l.isEmpty() && Strings.isBlank(l.get(l.size()-1))) l = l.subList(0, l.size()-1);
            return l;
        }

        Object handleNullish(List<String> lhs, List<String> rhs) {
            return processMaybe(lhs, null).or(() -> process(rhs));
        }

        Maybe<Object> processMaybe(List<String> lhs, Function<String,TypeToken<?>> explicitType) {
            try {
                Object result = process(lhs);
                if (result!=null) return Maybe.of(result);
                return Maybe.absent("null");

            } catch (Exception e) {
                if (Exceptions.isCausedByInterruptInAnyThread(e) && !Thread.currentThread().isInterrupted()) {
                    // value was unavailable, pass through to RHS
                    return Maybe.absent("unavailable");

                } else {
                    Exceptions.propagateIfFatal(e);
                }

                if (log.isTraceEnabled()) {
                    log.trace("Non-fatal exception processing expression "+ lhs +" (in context where there is an alterantive)", e);
                }
                return Maybe.absent(e);
            }
        }

        Maybe<Integer> asInteger(Object x) {
            Maybe<Integer> xi = TypeCoercions.tryCoerce(x, Integer.class);
            Maybe<Double> xd = asDouble(x);
            if (xi.isAbsent() || xd.isAbsent()) return xi;
            if (Math.abs(xd.get() - xi.get())<0.0000000001) return xi;
            return Maybe.absent("Double value does not match integer value");
        }

        Maybe<Double> asDouble(Object x) {
            Maybe<Double> v = TypeCoercions.tryCoerce(x, Double.class);
            if (v.isPresent() && !Double.isFinite(v.get())) return Maybe.absent(() -> new IllegalArgumentException("Value cannot be coerced to double: "+v));
            return v;
        }

        Object applyMathOperator(String op, List<String> lhs0, List<String> rhs0, BiFunction<Integer,Integer,Number> ifInt, BiFunction<Double,Double,Number> ifDouble) {
            Object lhs = process(lhs0);
            Object rhs = process(rhs0);

            if ("+".equals(op)) {
                if (lhs instanceof Duration) {
                    if (rhs instanceof Instant || rhs instanceof Date) {
                        Object newRhs = lhs;
                        lhs = rhs;
                        rhs = newRhs;
                        // fall through to below
                    } else {
                        return TypeCoercions.coerce(rhs, Duration.class).add((Duration) lhs);
                    }
                }
                if (lhs instanceof Instant) return TypeCoercions.coerce(rhs, Duration.class).addTo((Instant) lhs);
                if (lhs instanceof Date)
                    return new Timestamp((Instant) TypeCoercions.coerce(rhs, Duration.class).addTo(((Date) lhs).toInstant()));
            } else if ("-".equals(op)) {
                if (lhs instanceof Duration) {
                    return ((Duration)lhs).subtract(TypeCoercions.coerce(rhs, Duration.class));
                }
                if (lhs instanceof Instant) {
                    if (rhs instanceof Instant) return Duration.between((Instant)rhs, (Instant)lhs);
                    return TypeCoercions.coerce(rhs, Duration.class).multiply(-1).addTo((Instant) lhs);
                }
                if (lhs instanceof Date) {
                    if (rhs instanceof Date) return Duration.between(((Date)rhs).toInstant(), ((Date)lhs).toInstant());
                    return new Timestamp((Instant) TypeCoercions.coerce(rhs, Duration.class).multiply(-1).addTo(((Date) lhs).toInstant()));
                }
            }

            Maybe<Integer> lhsI = asInteger(lhs);
            Maybe<Integer> rhsI = asInteger(rhs);
            if (lhsI.isPresent() && rhsI.isPresent()) {
                Number x = ifInt.apply(lhsI.get(), rhsI.get());
                return ((Maybe)asInteger(x)).orMaybe(() -> asDouble(x)).get();
            }

            if (ifDouble!=null) {
                Maybe<Double> lhsD = asDouble(lhs);
                Maybe<Double> rhsD = asDouble(rhs);
                if (lhsD.isPresent() && rhsD.isPresent()) return asDouble(ifDouble.apply(lhsD.get(), rhsD.get())).get();

                if (lhsD.isAbsent()) failOnInvalidArgument("left", op, lhs0, lhs);
                if (rhsD.isAbsent()) failOnInvalidArgument("right", op, rhs0, rhs);
            } else {
                if (lhsI.isAbsent()) failOnInvalidArgument("left", op, lhs0, lhs);
                if (rhsI.isAbsent()) failOnInvalidArgument("right", op, rhs0, rhs);
            }

            throw new IllegalArgumentException("Should not come here");
        }

        Object applyBooleanOperator(List<String> lhs0, List<String> rhs0, BiFunction<Boolean, Boolean, Boolean> biFn) {
            Object lhs = process(lhs0);
            Object rhs = process(rhs0);

            Maybe<Boolean> lhsB = asBoolean(lhs);
            Maybe<Boolean> rhsB = asBoolean(rhs);
            if (lhsB.isPresent() && rhsB.isPresent()) {
                return biFn.apply(lhsB.get(), rhsB.get());
            }
            throw new IllegalArgumentException("Should not come here");
        }

        boolean applyComparison(List<String> lhs0, List<String> rhs0, Function<Integer, Boolean> test) {
            Object lhs = process(lhs0);
            Object rhs = process(rhs0);

            return DslPredicates.coercedCompare(lhs, rhs, test);
        }

        Maybe<Boolean> asBoolean(Object x) {
            return TypeCoercions.tryCoerce(x, Boolean.class);
        }

        private IllegalArgumentException failOnInvalidArgument(String side, String op, Object pre, Object post) {
            String msg = "Invalid "+side+" argument to operation '"+op+"'";

            String postS = ""+post;
            if (postS.contains("*") || postS.contains("+") || postS.contains("+") || postS.contains("/")) {
                // we could weaken this contraint but for now at least make it clear
                msg += "; mathematical operations must have spaces around them for disambiguation";
            }

            throw new IllegalArgumentException(msg + ": "+pre+" => "+post);
        }

        Object handleMultiply(List<String> lhs, List<String> rhs) {
            return applyMathOperator("*", lhs, rhs, (a,b)->a*b, (a,b)->a*b);
        }

        Object handleDivide(List<String> lhs, List<String> rhs) {
            return applyMathOperator("/", lhs, rhs, (a,b)->1.0*a/b, (a,b)->a/b);
        }

        Object handleBooleanAnd(List<String> lhs, List<String> rhs) {
            return applyBooleanOperator(lhs, rhs, (a, b) -> a && b);
        }

        Object handleBooleanOr(List<String> lhs, List<String> rhs) {
            return applyBooleanOperator(lhs, rhs, (a, b) -> a || b);
        }

        Object handleOrderedGreaterThan(List<String> lhs, List<String> rhs) {
            return applyComparison(lhs, rhs, v -> v>0);
        }

        Object handleOrderedGreaterThanOrEqual(List<String> lhs, List<String> rhs) {
            return applyComparison(lhs, rhs, v -> v>=0);
        }

        Object handleOrderedLessThan(List<String> lhs, List<String> rhs) {
            return applyComparison(lhs, rhs, v -> v<0);
        }

        Object handleOrderedLessThanOrEqual(List<String> lhs, List<String> rhs) {
            return applyComparison(lhs, rhs, v -> v<=0);
        }

        boolean handleEquals(List<String> lhs, List<String> rhs) {
            return DslPredicates.coercedEqual(process(lhs), process(rhs));
        }

        Object handleTernaryCondition(List<String> lhs0, List<String> rhs0) {
            //log.info(String.format("Ternary Condition 0: [lhs:%s][rhs:%s]", lhs0, rhs0));
            Object lhs = process(lhs0);
            Object rhs;
            int questionIndex = rhs0.indexOf("?");
            int colonIndex = rhs0.indexOf(":");
            if (questionIndex > -1 && questionIndex < colonIndex) {
                // Nested ternary
                rhs = handleNestedTernaryRhs(rhs0);
            } else if (questionIndex > -1 && colonIndex < questionIndex) {
                // Chained ternary
                rhs = handleChainedTernaryRhs(rhs0);
            } else {
                // non-nested or chained
                rhs = process(rhs0, true);
            }
            //log.info(String.format("Ternary Condition 1: [lhs:%s][rhs:%s]", lhs, rhs));

            if (!(rhs instanceof TernaryArms)) throw new IllegalArgumentException("Mismatched ternary ':' operator");

            Maybe<Boolean> condition = asBoolean(lhs);
            if (condition.isPresent()){
                if (condition.get()) {
                    // ? left : right -- rhs length is 5 [left, ,:, ,right]
                    // ? true && true : false || false -- rhs length is ???
                    return process( ((TernaryArms)rhs).getLeft());
                    //throw new IllegalArgumentException("TERNARY CONDITION IS TRUE");
                } else {
                    return process( ((TernaryArms)rhs).getRight());
                    //throw new IllegalArgumentException("TERNARY CONDITION IS FALSE");
                }
            }

            throw new IllegalArgumentException("Leading term of ternary '"+lhs+"' does not evaluate to a boolean");
        }

        public TernaryArms handleNestedTernaryRhs(List<String> rhs) {
            int lastColonIndex = rhs.lastIndexOf(":");
            if (lastColonIndex == -1) {
                throw new IllegalArgumentException("Mismatched ternary ':' operator");
            }
            int firstColonIndex = rhs.indexOf(":");
            if (firstColonIndex == lastColonIndex) {
                return (TernaryArms) process(rhs);
            }
            return new TernaryArms(trim(rhs.subList(0, lastColonIndex)), trim(rhs.subList(lastColonIndex + 1, rhs.size())));
        }

        public TernaryArms handleChainedTernaryRhs(List<String> rhs) {
            int colonIndex = rhs.indexOf(":");
            if (colonIndex == -1) {
                throw new IllegalArgumentException("Mismatched ternary ':' operator");
            }
            return new TernaryArms(trim(rhs.subList(0, colonIndex)), trim(rhs.subList(colonIndex + 1, rhs.size())));
        }

        static class TernaryArms extends MutablePair<List<String>,List<String>> {
            public TernaryArms(List<String> lhs, List<String> rhs) {
                super(lhs, rhs);
            }
        }

        public Object handleTernaryArms(List<String> lhs0, List<String> rhs0) {
            //log.info(String.format("Ternary 0: [lhs:%s][rhs:%s]", lhs0, rhs0));
            return new TernaryArms(lhs0, rhs0);
        }

        Object handleAdd(List<String> lhs, List<String> rhs) {
            return applyMathOperator("+", lhs, rhs, (a,b)->a+b, (a,b)->a+b);
        }

        Object handleSubtract(List<String> lhs, List<String> rhs) {
            return applyMathOperator("-", lhs, rhs, (a,b)->a-b, (a,b)->a-b);
        }

        Object handleModulo(List<String> lhs, List<String> rhs) {
            return applyMathOperator("%", lhs, rhs, (a,b)->a%b, null);
        }
    }

    @Override protected Boolean isDefaultIdempotent() { return true; }

}
