/*
 * 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 freemarker.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import freemarker.template.SimpleScalar;
import freemarker.template.SimpleSequence;
import freemarker.template.TemplateCollectionModelEx;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template._ObjectWrappers;
import freemarker.template._TemplateAPI;
import freemarker.template._VersionInts;
import freemarker.template.utility.Constants;

/**
 * {@code target[keyExpression]}, where, in FM 2.3, {@code keyExpression} can be string, a number or a range,
 * and {@code target} can be a hash or a sequence.
 */
class DynamicKeyName extends Expression {

    private static final int UNKNOWN_RESULT_SIZE = -1;

    private final Expression keyExpression;
    private final Expression target;
    private boolean lazilyGeneratedResultEnabled;

    DynamicKeyName(Expression target, Expression keyExpression) {
        this.target = target; 
        this.keyExpression = keyExpression;

        target.enableLazilyGeneratedResult();
    }

    DynamicKeyName(DynamicKeyName dynamicKeyName) {
        this(dynamicKeyName.target, dynamicKeyName.keyExpression);
        this.lazilyGeneratedResultEnabled = dynamicKeyName.lazilyGeneratedResultEnabled;
        this.constantValue = dynamicKeyName.constantValue; // Probably always will be null here
        copyFieldsFrom(dynamicKeyName);
    }

    @Override
    TemplateModel _eval(Environment env) throws TemplateException {
        TemplateModel targetModel = target.eval(env);
        if (targetModel == null) {
            if (env.isClassicCompatible()) {
                return null;
            } else {
                throw InvalidReferenceException.getInstance(target, env);
            }
        }
        
        TemplateModel keyModel = keyExpression.eval(env);
        if (keyModel == null) {
            if (env.isClassicCompatible()) {
                keyModel = TemplateScalarModel.EMPTY_STRING;
            } else {
                keyExpression.assertNonNull(null, env);
            }
        }
        if (keyModel instanceof TemplateNumberModel) {
            int index = keyExpression.modelToNumber(keyModel, env).intValue();
            return dealWithNumericalKey(targetModel, index, env);
        }
        if (keyModel instanceof TemplateScalarModel) {
            String key = EvalUtil.modelToString((TemplateScalarModel) keyModel, keyExpression, env);
            return dealWithStringKey(targetModel, key, env);
        }
        if (keyModel instanceof RangeModel) {
            return dealWithRangeKey(targetModel, (RangeModel) keyModel, env);
        }
        throw new UnexpectedTypeException(keyExpression, keyModel, "number, range, or string",
                new Class[] { TemplateNumberModel.class, TemplateScalarModel.class, Range.class }, env);
    }

    static private Class[] NUMERICAL_KEY_LHO_EXPECTED_TYPES;
    static {
        NUMERICAL_KEY_LHO_EXPECTED_TYPES = new Class[1 + NonStringException.STRING_COERCABLE_TYPES.length];
        NUMERICAL_KEY_LHO_EXPECTED_TYPES[0] = TemplateSequenceModel.class;
        for (int i = 0; i < NonStringException.STRING_COERCABLE_TYPES.length; i++) {
            NUMERICAL_KEY_LHO_EXPECTED_TYPES[i + 1] = NonStringException.STRING_COERCABLE_TYPES[i];
        }
    }
    
    private TemplateModel dealWithNumericalKey(TemplateModel targetModel, 
                                               int index, 
                                               Environment env)
        throws TemplateException {
        if (targetModel instanceof TemplateSequenceModel) {
            TemplateSequenceModel tsm = (TemplateSequenceModel) targetModel;
            int size;
            try {
                size = tsm.size();
            } catch (Exception e) {
                size = Integer.MAX_VALUE;
            }
            return index < size ? tsm.get(index) : null;
        }
        if (targetModel instanceof LazilyGeneratedCollectionModel
                && ((LazilyGeneratedCollectionModel) targetModel).isSequence()) {
            if (index < 0) {
                return null;
            }
            TemplateModelIterator iter = ((LazilyGeneratedCollectionModel) targetModel).iterator();
            for (int curIndex = 0; iter.hasNext(); curIndex++) {
                TemplateModel next = iter.next();
                if (index == curIndex) {
                    return next;
                }
            }
            return null;
        }

        // Fall back to get a character from a string
        try {
            String s = target.evalAndCoerceToPlainText(env);
            try {
                return new SimpleScalar(s.substring(index, index + 1));
            } catch (IndexOutOfBoundsException e) {
                if (index < 0) {
                    throw new _MiscTemplateException("Negative index not allowed: ", Integer.valueOf(index));
                }
                if (index >= s.length()) {
                    throw new _MiscTemplateException(
                            "String index out of range: The index was ", Integer.valueOf(index),
                            " (0-based), but the length of the string is only ", Integer.valueOf(s.length()) , ".");
                }
                throw new RuntimeException("Can't explain exception", e);
            }
        } catch (NonStringException e) {
            throw new UnexpectedTypeException(
                    target, targetModel,
                    "sequence or " + NonStringException.STRING_COERCABLE_TYPES_DESC,
                    NUMERICAL_KEY_LHO_EXPECTED_TYPES,
                    (targetModel instanceof TemplateHashModel
                            ? "You had a numerical value inside the []. Currently that's only supported for "
                                    + "sequences (lists) and strings. To get a Map item with a non-string key, "
                                    + "use myMap?api.get(myKey)."
                            : null),
                    env);
        }
    }

    private TemplateModel dealWithStringKey(TemplateModel targetModel, String key, Environment env)
        throws TemplateException {
        if (targetModel instanceof TemplateHashModel) {
            return getFromHashModelWithStringKey((TemplateHashModel) targetModel, key);
        }
        throw new NonHashException(target, targetModel, env);
    }

    protected TemplateModel getFromHashModelWithStringKey(TemplateHashModel targetModel, String key)
            throws TemplateException {
        return targetModel.get(key);
    }

    private TemplateModel dealWithRangeKey(TemplateModel targetModel, RangeModel range, Environment env)
    throws TemplateException {
        // We can have 3 kind of left hand operands ("targets"): sequence, lazily generated sequence, string
        final TemplateSequenceModel targetSeq;
        final LazilyGeneratedCollectionModel targetLazySeq;
        final String targetStr;
        if (targetModel instanceof TemplateSequenceModel) {
            targetSeq = (TemplateSequenceModel) targetModel;
            targetLazySeq = null;
            targetStr = null;
        } else if (targetModel instanceof LazilyGeneratedCollectionModel
                && ((LazilyGeneratedCollectionModel) targetModel).isSequence()) {
            targetSeq = null;
            targetLazySeq = (LazilyGeneratedCollectionModel) targetModel;
            targetStr = null;
        } else {
            targetSeq = null;
            targetLazySeq = null;
            try {
                targetStr = target.evalAndCoerceToPlainText(env);
            } catch (NonStringException e) {
                throw new UnexpectedTypeException(
                        target, target.eval(env),
                        "sequence or " + NonStringException.STRING_COERCABLE_TYPES_DESC,
                        NUMERICAL_KEY_LHO_EXPECTED_TYPES, env);
            }
        }
        
        final int rangeSize = range.size(); // Warning: Value is meaningless for right unbounded sequences
        final boolean rightUnbounded = range.isRightUnbounded();
        final boolean rightAdaptive = range.isRightAdaptive(); // Always true if rightUnbounded
        
        // Empty ranges are accepted even if the begin index is out of bounds. That's because a such range
        // produces an empty sequence, which thus doesn't contain any illegal indexes.
        if (!rightUnbounded && rangeSize == 0) {
            return emptyResult(targetSeq != null);
        }

        final int firstIdx = range.getBegining();
        if (firstIdx < 0) {
            throw new _MiscTemplateException(keyExpression,
                    "Negative range start index (", Integer.valueOf(firstIdx),
                    ") isn't allowed for a range used for slicing.");
        }

        final int step = range.getStep(); // Currently always 1 or -1

        final int targetSize;
        final boolean targetSizeKnown; // Didn't want to use targetSize = -1, as we don't control the seq.size() impl.
        if (targetStr != null) {
            targetSize = targetStr.length();
            targetSizeKnown = true;
        } else if (targetSeq != null) {
            targetSize = targetSeq.size();
            targetSizeKnown = true;
        } else if (targetLazySeq instanceof TemplateCollectionModelEx) {
            // E.g. the size of seq?map(f) is known, despite that the elements are lazily calculated.
            targetSize = ((TemplateCollectionModelEx) targetLazySeq).size();
            targetSizeKnown = true;
        } else {
            targetSize = Integer.MAX_VALUE;
            targetSizeKnown = false;
        }

        if (targetSizeKnown) {
            // Right-adaptive increasing ranges can start 1 after the last element of the target, because they are like
            // ranges with exclusive end index of at most targetSize. Hence a such range is just an empty list of
            // indexes, and thus it isn't out-of-bounds.
            // Right-adaptive decreasing ranges has exclusive end -1, so it can't help on a too high firstIndex.
            // Right-bounded ranges at this point aren't empty, so firstIndex == targetSize can't be allowed.
            if (rightAdaptive && step == 1 ? firstIdx > targetSize : firstIdx >= targetSize) {
                throw new _MiscTemplateException(keyExpression,
                        "Range start index ", Integer.valueOf(firstIdx), " is out of bounds, because the sliced ",
                        (targetStr != null ? "string" : "sequence"),
                        " has only ", Integer.valueOf(targetSize), " ",
                        (targetStr != null ? "character(s)" : "element(s)"),
                        ". ", "(Note that indices are 0-based).");
            }
        }

        // Calculate resultSize. Note that:
        // - It might will be UNKNOWN_RESULT_SIZE when targetLazySeq != null.
        // - It might will be out-of-bounds if !targetSizeKnown (otherwise we validate if the range is correct)
        final int resultSize;
        if (!rightUnbounded) {
            final int lastIdx = firstIdx + (rangeSize - 1) * step; // Note: lastIdx is inclusive
            if (lastIdx < 0) {
                if (!rightAdaptive) {
                    throw new _MiscTemplateException(keyExpression,
                            "Negative range end index (", Integer.valueOf(lastIdx),
                            ") isn't allowed for a range used for slicing.");
                } else {
                    resultSize = firstIdx + 1;
                }
            } else if (targetSizeKnown && lastIdx >= targetSize) {
                if (!rightAdaptive) {
                    throw new _MiscTemplateException(keyExpression,
                            "Range end index ", Integer.valueOf(lastIdx), " is out of bounds, because the sliced ",
                            (targetStr != null ? "string" : "sequence"),
                            " has only ", Integer.valueOf(targetSize), " ", (targetStr != null ? "character(s)" : "element(s)"),
                            ". (Note that indices are 0-based).");
                } else {
                    resultSize = Math.abs(targetSize - firstIdx);
                }
            } else {
                resultSize = rangeSize;
            }
        } else { // rightUnbounded
            resultSize = targetSizeKnown ? targetSize - firstIdx : UNKNOWN_RESULT_SIZE;
        }
        
        if (resultSize == 0) {
            return emptyResult(targetSeq != null);
        }
        if (targetSeq != null) {
            // In principle we should take lazilyGeneratedResultEnabled into account, but that wouldn't be backward
            // compatible. For example, with lazily generated sequence result <#list xs[b..e] as x> would behave
            // differently if xs is modified inside the #list nested content.
            ArrayList<TemplateModel> resultList = new ArrayList<>(resultSize);
            int srcIdx = firstIdx;
            for (int i = 0; i < resultSize; i++) {
                resultList.add(targetSeq.get(srcIdx));
                srcIdx += step;
            }
            // List items are already wrapped:
            return new SimpleSequence(resultList, _ObjectWrappers.SAFE_OBJECT_WRAPPER);
        } else if (targetLazySeq != null) {
            // As a targetLazySeq can only occur if a new built-in like ?filter or ?map was used somewhere in the target
            // expression, in this case we can return lazily generated sequence without breaking backward compatibility.
            if (step == 1) {
                return getStep1RangeFromIterator(targetLazySeq.iterator(), range, resultSize, targetSizeKnown);
            } else if (step == -1) {
                return getStepMinus1RangeFromIterator(targetLazySeq.iterator(), range, resultSize);
            } else {
                throw new AssertionError();
            }
        } else {
            final int exclEndIdx;
            if (step < 0 && resultSize > 1) {
                if (!(range.isAffectedByStringSlicingBug() && resultSize == 2)) {
                    throw new _MiscTemplateException(keyExpression,
                            "Decreasing ranges aren't allowed for slicing strings (as it would give reversed text). "
                            + "The index range was: first = ", Integer.valueOf(firstIdx),
                            ", last = ", Integer.valueOf(firstIdx + (resultSize - 1) * step));
                } else {
                    // Emulate the legacy bug, where "foo"[n .. n-1] gives "" instead of an error (if n >= 1).  
                    // Fix this in FTL [2.4]
                    exclEndIdx = firstIdx;
                }
            } else {
                exclEndIdx = firstIdx + resultSize;
            }
            
            return new SimpleScalar(targetStr.substring(firstIdx, exclEndIdx));
        }
    }

    private TemplateModel getStep1RangeFromIterator(
            final TemplateModelIterator targetIter, final RangeModel range, int resultSize, boolean targetSizeKnown)
            throws TemplateModelException {
        final int firstIdx = range.getBegining();
        final int lastIdx = firstIdx + (range.size() - 1); // Note: meaningless if the range is right unbounded
        final boolean rightAdaptive = range.isRightAdaptive();
        final boolean rightUnbounded = range.isRightUnbounded();
        if (lazilyGeneratedResultEnabled) {
            TemplateModelIterator iterator = new TemplateModelIterator() {
                private boolean elementsBeforeFirsIndexWereSkipped;
                private int nextIdx;

                @Override
                public TemplateModel next() throws TemplateModelException {
                    ensureElementsBeforeFirstIndexWereSkipped();
                    if (!rightUnbounded && nextIdx > lastIdx) {
                        // We fail because the consumer of this iterator hasn't used hasNext() properly.
                        throw new _TemplateModelException(
                                "Iterator has no more elements (at index ", Integer.valueOf(nextIdx), ")");
                    }
                    if (!rightAdaptive && !targetIter.hasNext()) {
                        // We fail because the range was wrong, not because of the consumer of this iterator .
                        throw newRangeEndOutOfBoundsException(nextIdx, lastIdx);
                    }
                    TemplateModel result = targetIter.next();
                    nextIdx++;
                    return result;
                }

                @Override
                public boolean hasNext() throws TemplateModelException {
                    ensureElementsBeforeFirstIndexWereSkipped();
                    return (rightUnbounded || nextIdx <= lastIdx) && (!rightAdaptive || targetIter.hasNext());
                }

                public void ensureElementsBeforeFirstIndexWereSkipped() throws TemplateModelException {
                    if (elementsBeforeFirsIndexWereSkipped) {
                        return;
                    }

                    skipElementsBeforeFirstIndex(targetIter, firstIdx);
                    nextIdx = firstIdx;
                    elementsBeforeFirsIndexWereSkipped = true;
                }
            };
            return resultSize != UNKNOWN_RESULT_SIZE && targetSizeKnown  // targetSizeKnown => range end was validated
                    ? new LazilyGeneratedCollectionModelWithAlreadyKnownSize(iterator, resultSize, true)
                    : new LazilyGeneratedCollectionModelWithUnknownSize(iterator, true);
        } else { // !lazilyGeneratedResultEnabled
            List<TemplateModel> resultList = resultSize != UNKNOWN_RESULT_SIZE
                    ? new ArrayList<TemplateModel>(resultSize)
                    : new ArrayList<TemplateModel>();
            skipElementsBeforeFirstIndex(targetIter, firstIdx);
            collectElements: for (int nextIdx = firstIdx; rightUnbounded || nextIdx <= lastIdx; nextIdx++) {
                if (!targetIter.hasNext()) {
                    if (!rightAdaptive) {
                        throw newRangeEndOutOfBoundsException(nextIdx, lastIdx);
                    }
                    break collectElements;
                }
                resultList.add(targetIter.next());
            }
            // List items are already wrapped:
            return new SimpleSequence(resultList, _ObjectWrappers.SAFE_OBJECT_WRAPPER);
        }
    }

    private void skipElementsBeforeFirstIndex(TemplateModelIterator targetIter, int firstIdx) throws TemplateModelException {
        int nextIdx = 0;
        while (nextIdx < firstIdx) {
            if (!targetIter.hasNext()) {
                throw new _TemplateModelException(keyExpression,
                        "Range start index ", Integer.valueOf(firstIdx),
                        " is out of bounds, as the sliced sequence only has ", nextIdx, " elements.");
            }
            targetIter.next();
            nextIdx++;
        }
    }

    private _TemplateModelException newRangeEndOutOfBoundsException(int nextIdx, int lastIdx) {
        return new _TemplateModelException(keyExpression,
                "Range end index ", Integer.valueOf(lastIdx), " is out of bounds, as sliced sequence " +
                "only has ", nextIdx, " elements.");
    }

    // Because the order has to be reversed, we have to "buffer" the stream in this case.
    private TemplateModel getStepMinus1RangeFromIterator(TemplateModelIterator targetIter, RangeModel range,
            int resultSize)
            throws TemplateException {
        int highIndex = range.getBegining();
        // Low index was found to be valid earlier. So now something like [2..*-9] becomes to [2..0] in effect.
        int lowIndex = Math.max(highIndex - (range.size() - 1), 0);

        final TemplateModel[] resultElements = new TemplateModel[highIndex - lowIndex + 1];

        int srcIdx = 0; // With an Iterator we can only start from index 0
        int dstIdx = resultElements.length - 1; // Write into the result array backwards
        while (srcIdx <= highIndex && targetIter.hasNext()) {
            TemplateModel element = targetIter.next();
            if (srcIdx >= lowIndex) {
                resultElements[dstIdx--] = element;
            }
            srcIdx++;
        }
        if (dstIdx != -1) {
            throw new _MiscTemplateException(DynamicKeyName.this,
                    "Range top index " + highIndex + " (0-based) is outside the sliced sequence of length " +
                    srcIdx + ".");
        }
        return new SimpleSequence(Arrays.asList(resultElements), _ObjectWrappers.SAFE_OBJECT_WRAPPER);
    }

    private TemplateModel emptyResult(boolean seq) {
        return seq
                ? (_TemplateAPI.getTemplateLanguageVersionAsInt(this) < _VersionInts.V_2_3_21
                        ? new SimpleSequence(_ObjectWrappers.SAFE_OBJECT_WRAPPER)
                        : Constants.EMPTY_SEQUENCE)
                : TemplateScalarModel.EMPTY_STRING;
    }

    @Override
    void enableLazilyGeneratedResult() {
        lazilyGeneratedResultEnabled = true;
    }

    @Override
    public String getCanonicalForm() {
        return target.getCanonicalForm() 
               + "[" 
               + keyExpression.getCanonicalForm() 
               + "]";
    }
    
    @Override
    String getNodeTypeSymbol() {
        return "...[...]";
    }
    
    @Override
    boolean isLiteral() {
        return constantValue != null || (target.isLiteral() && keyExpression.isLiteral());
    }
    
    @Override
    int getParameterCount() {
        return 2;
    }

    @Override
    Object getParameterValue(int idx) {
        return idx == 0 ? target : keyExpression;
    }

    @Override
    ParameterRole getParameterRole(int idx) {
        return idx == 0 ? ParameterRole.LEFT_HAND_OPERAND : ParameterRole.ENCLOSED_OPERAND;
    }

    @Override
    protected Expression deepCloneWithIdentifierReplaced_inner(
            String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) {
    	return new DynamicKeyName(
    	        target.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState),
    	        keyExpression.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState));
    }
}
