/*
 * 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.HashSet;
import java.util.List;
import java.util.Set;

import freemarker.template.SimpleNumber;
import freemarker.template.SimpleScalar;
import freemarker.template.SimpleSequence;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateHashModelEx;
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;

/**
 * An operator for the + operator. Note that this is treated
 * separately from the other 4 arithmetic operators,
 * since + is overloaded to mean string concatenation.
 */
final class AddConcatExpression extends Expression {

    private final Expression left;
    private final Expression right;

    AddConcatExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    TemplateModel _eval(Environment env) throws TemplateException {
        return _eval(env, this, left, left.eval(env), right, right.eval(env));
    }

    /**
     * @param leftExp
     *            Used for error messages only; can be {@code null}
     * @param rightExp
     *            Used for error messages only; can be {@code null}
     */
    static TemplateModel _eval(Environment env,
            TemplateObject parent,
            Expression leftExp, TemplateModel leftModel,
            Expression rightExp, TemplateModel rightModel)
            throws TemplateModelException, TemplateException, NonStringException {
        if (leftModel instanceof TemplateNumberModel && rightModel instanceof TemplateNumberModel) {
            Number first = EvalUtil.modelToNumber((TemplateNumberModel) leftModel, leftExp);
            Number second = EvalUtil.modelToNumber((TemplateNumberModel) rightModel, rightExp);
            return _evalOnNumbers(env, parent, first, second);
        } else if (leftModel instanceof TemplateSequenceModel && rightModel instanceof TemplateSequenceModel) {
            return new ConcatenatedSequence((TemplateSequenceModel) leftModel, (TemplateSequenceModel) rightModel);
        } else {
            boolean hashConcatPossible
                    = leftModel instanceof TemplateHashModel && rightModel instanceof TemplateHashModel;
            try {
                // We try string addition first. If hash addition is possible, then instead of throwing exception
                // we return null and do hash addition instead. (We can't simply give hash addition a priority, like
                // with sequence addition above, as FTL strings are often also FTL hashes.)
                Object leftOMOrStr = EvalUtil.coerceModelToStringOrMarkup(
                        leftModel, leftExp, /* returnNullOnNonCoercableType = */ hashConcatPossible, null,
                        env);
                if (leftOMOrStr == null) {
                    return _eval_concatenateHashes(leftModel, rightModel);
                }

                // Same trick with null return as above.
                Object rightOMOrStr = EvalUtil.coerceModelToStringOrMarkup(
                        rightModel, rightExp, /* returnNullOnNonCoercableType = */ hashConcatPossible, null,
                        env);
                if (rightOMOrStr == null) {
                    return _eval_concatenateHashes(leftModel, rightModel);
                }

                if (leftOMOrStr instanceof String) {
                    if (rightOMOrStr instanceof String) {
                        return new SimpleScalar(((String) leftOMOrStr).concat((String) rightOMOrStr));
                    } else { // rightOMOrStr instanceof TemplateMarkupOutputModel
                        TemplateMarkupOutputModel<?> rightMO = (TemplateMarkupOutputModel<?>) rightOMOrStr; 
                        return EvalUtil.concatMarkupOutputs(parent,
                                rightMO.getOutputFormat().fromPlainTextByEscaping((String) leftOMOrStr),
                                rightMO);
                    }                    
                } else { // leftOMOrStr instanceof TemplateMarkupOutputModel 
                    TemplateMarkupOutputModel<?> leftMO = (TemplateMarkupOutputModel<?>) leftOMOrStr; 
                    if (rightOMOrStr instanceof String) {  // markup output
                        return EvalUtil.concatMarkupOutputs(parent,
                                leftMO,
                                leftMO.getOutputFormat().fromPlainTextByEscaping((String) rightOMOrStr));
                    } else { // rightOMOrStr instanceof TemplateMarkupOutputModel
                        return EvalUtil.concatMarkupOutputs(parent,
                                leftMO,
                                (TemplateMarkupOutputModel<?>) rightOMOrStr);
                    }
                }
            } catch (NonStringOrTemplateOutputException e) {
                // 2.4: Remove this catch; it's for BC, after reworking hash addition so it doesn't rely on this. But
                // user code might throws this (very unlikely), and then in 2.3.x we did catch that too, incorrectly.
                if (hashConcatPossible) {
                    return _eval_concatenateHashes(leftModel, rightModel);
                } else {
                    throw e;
                }
            }
        }
    }

    private static TemplateModel _eval_concatenateHashes(TemplateModel leftModel, TemplateModel rightModel)
            throws TemplateModelException {
        if (leftModel instanceof TemplateHashModelEx && rightModel instanceof TemplateHashModelEx) {
            TemplateHashModelEx leftModelEx = (TemplateHashModelEx) leftModel;
            TemplateHashModelEx rightModelEx = (TemplateHashModelEx) rightModel;
            if (leftModelEx.size() == 0) {
                return rightModelEx;
            } else if (rightModelEx.size() == 0) {
                return leftModelEx;
            } else {
                return new ConcatenatedHashEx(leftModelEx, rightModelEx);
            }
        } else {
            return new ConcatenatedHash((TemplateHashModel) leftModel,
                                        (TemplateHashModel) rightModel);
        }
    }

    static TemplateModel _evalOnNumbers(Environment env, TemplateObject parent, Number first, Number second)
            throws TemplateException {
        ArithmeticEngine ae = EvalUtil.getArithmeticEngine(env, parent);
        return new SimpleNumber(ae.add(first, second));
    }

    @Override
    boolean isLiteral() {
        return constantValue != null || (left.isLiteral() && right.isLiteral());
    }

    @Override
    protected Expression deepCloneWithIdentifierReplaced_inner(
            String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) {
    	return new AddConcatExpression(
    	left.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState),
    	right.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState));
    }

    @Override
    public String getCanonicalForm() {
        return left.getCanonicalForm() + " + " + right.getCanonicalForm();
    }
    
    @Override
    String getNodeTypeSymbol() {
        return "+";
    }
    
    @Override
    int getParameterCount() {
        return 2;
    }

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

    @Override
    ParameterRole getParameterRole(int idx) {
        return ParameterRole.forBinaryOperatorOperand(idx);
    }

    // Non-private for unit testing
    static final class ConcatenatedSequence
    implements
        TemplateSequenceModel, TemplateCollectionModel {
        private final TemplateSequenceModel left;
        private final TemplateSequenceModel right;

        ConcatenatedSequence(TemplateSequenceModel left, TemplateSequenceModel right) {
            this.left = left;
            this.right = right;
        }

        @Override
        public int size() throws TemplateModelException {
            int totalSize = 0;

            ConcatenatedSequence[] concSeqsWithRightPending = new ConcatenatedSequence[2];
            int concSeqsWithRightPendingLength = 0;
            ConcatenatedSequence concSeqInFocus = this;

            while (true) {
                TemplateSequenceModel left;
                while ((left = concSeqInFocus.left) instanceof ConcatenatedSequence) {
                    if (concSeqsWithRightPendingLength == concSeqsWithRightPending.length) {
                        concSeqsWithRightPending = Arrays.copyOf(concSeqsWithRightPending, concSeqsWithRightPendingLength * 2);
                    }
                    concSeqsWithRightPending[concSeqsWithRightPendingLength++] = concSeqInFocus;
                    concSeqInFocus = (ConcatenatedSequence) left;
                }
                totalSize += left.size();

                while (true) {
                    TemplateSequenceModel right = concSeqInFocus.right;
                    if (right instanceof ConcatenatedSequence) {
                        concSeqInFocus = (ConcatenatedSequence) right;
                        break; // To jump at the left-descending loop
                    }
                    totalSize += right.size();

                    if (concSeqsWithRightPendingLength == 0) {
                        return totalSize;
                    }

                    concSeqsWithRightPendingLength--;
                    concSeqInFocus = concSeqsWithRightPending[concSeqsWithRightPendingLength];
                }
            }
        }

        @Override
        public TemplateModel get(int index) throws TemplateModelException {
            if (index < 0) {
                return null;
            }

            int totalSize = 0;

            ConcatenatedSequence[] concSeqsWithRightPending = new ConcatenatedSequence[2];
            int concSeqsWithRightPendingLength = 0;
            ConcatenatedSequence concSeqInFocus = this;

            while (true) {
                TemplateSequenceModel left;
                while ((left = concSeqInFocus.left) instanceof ConcatenatedSequence) {
                    if (concSeqsWithRightPendingLength == concSeqsWithRightPending.length) {
                        concSeqsWithRightPending = Arrays.copyOf(concSeqsWithRightPending, concSeqsWithRightPendingLength * 2);
                    }
                    concSeqsWithRightPending[concSeqsWithRightPendingLength++] = concSeqInFocus;
                    concSeqInFocus = (ConcatenatedSequence) left;
                }
                {
                    int segmentSize = left.size();
                    totalSize += segmentSize;
                    if (totalSize > index) {
                        return left.get(index - (totalSize - segmentSize));
                    }
                }

                while (true) {
                    TemplateSequenceModel right = concSeqInFocus.right;
                    if (right instanceof ConcatenatedSequence) {
                        concSeqInFocus = (ConcatenatedSequence) right;
                        break; // To jump at the left-descending loop
                    }
                    {
                        int segmentSize = right.size();
                        totalSize += segmentSize;
                        if (totalSize > index) {
                            return right.get(index - (totalSize - segmentSize));
                        }
                    }

                    if (concSeqsWithRightPendingLength == 0) {
                        return null;
                    }

                    concSeqsWithRightPendingLength--;
                    concSeqInFocus = concSeqsWithRightPending[concSeqsWithRightPendingLength];
                }
            }
        }

        @Override
        public TemplateModelIterator iterator() throws TemplateModelException {
            return new ConcatenatedSequenceIterator(this);
        }

    }

    private static class ConcatenatedSequenceIterator implements TemplateModelIterator {
        /** The path from the root down to the parent of {@link #currentSegment} */
        private final List<ConcatenatedSequence> concSeqsWithRightPending = new ArrayList<>();
        private ConcatenatedSequence concSeqWithLeftDescentPending;

        private TemplateSequenceModel currentSegment;
        private int currentSegmentNextIndex;
        private TemplateModelIterator currentSegmentIterator;

        private boolean hasPrefetchedResult;
        private TemplateModel prefetchedNext;
        private boolean prefetchedHasNext;

        public ConcatenatedSequenceIterator(ConcatenatedSequence concatSeq) throws TemplateModelException {
            // Descent down to the first nested sequence, and memorize the path down there
            concSeqWithLeftDescentPending = concatSeq;
        }

        @Override
        public TemplateModel next() throws TemplateModelException {
            ensureHasPrefetchedResult();

            if (!prefetchedHasNext) {
                throw new TemplateModelException("The collection has no more elements.");
            }

            TemplateModel result = prefetchedNext;
            hasPrefetchedResult = false; // To consume prefetched element
            prefetchedNext = null; // To not prevent GC
            return result;
        }

        @Override
        public boolean hasNext() throws TemplateModelException {
            ensureHasPrefetchedResult();
            return prefetchedHasNext;
        }

        private void ensureHasPrefetchedResult() throws TemplateModelException {
            if (hasPrefetchedResult) {
                return;
            }

            while (true) {
                // Try to fetch the next value from the current segment:
                if (currentSegmentIterator != null) {
                    boolean hasNext = currentSegmentIterator.hasNext();
                    if (hasNext) {
                        prefetchedNext = currentSegmentIterator.next();
                        prefetchedHasNext = true;
                        hasPrefetchedResult = true;
                        return;
                    } else {
                        currentSegmentIterator = null;
                        // Falls through
                    }
                } else if (currentSegment != null) {
                    int size = currentSegment.size();
                    if (currentSegmentNextIndex < size) {
                        prefetchedNext = currentSegment.get(currentSegmentNextIndex++);
                        prefetchedHasNext = true;
                        hasPrefetchedResult = true;
                        return;
                    } else {
                        currentSegment = null;
                        // Falls through
                    }
                } else if (concSeqWithLeftDescentPending != null) { // Nothing to fetch from, has to descend left first
                    ConcatenatedSequence leftDescentCurrentConcSeq = concSeqWithLeftDescentPending;
                    concSeqWithLeftDescentPending = null;
                    concSeqsWithRightPending.add(leftDescentCurrentConcSeq);

                    TemplateSequenceModel leftSeq;
                    while ((leftSeq = leftDescentCurrentConcSeq.left) instanceof ConcatenatedSequence) {
                        leftDescentCurrentConcSeq = (ConcatenatedSequence) leftSeq;
                        concSeqsWithRightPending.add(leftDescentCurrentConcSeq);
                    }
                    setCurrentSegment(leftSeq);
                    continue; // Jump to fetching from current segment
                }

                // If we reach this, then the current segment was fully consumed, so we have to switch to the next segment.

                if (concSeqsWithRightPending.isEmpty()) {
                    prefetchedNext = null;
                    prefetchedHasNext = false;
                    hasPrefetchedResult = true;
                    return;
                }

                TemplateSequenceModel right = concSeqsWithRightPending.remove(concSeqsWithRightPending.size() - 1).right;
                if (right instanceof ConcatenatedSequence) {
                    concSeqWithLeftDescentPending = (ConcatenatedSequence) right;
                } else {
                    setCurrentSegment(right);
                }
            }
        }

        private void setCurrentSegment(TemplateSequenceModel currentSegment) throws TemplateModelException {
            if (currentSegment instanceof TemplateCollectionModel) {
                this.currentSegmentIterator = ((TemplateCollectionModel) currentSegment).iterator();
                this.currentSegment = null;
            } else {
                this.currentSegment = currentSegment;
                this.currentSegmentNextIndex = 0;
                this.currentSegmentIterator = null;
            }
        }
    }

    private static class ConcatenatedHash
    implements TemplateHashModel {
        protected final TemplateHashModel left;
        protected final TemplateHashModel right;

        ConcatenatedHash(TemplateHashModel left, TemplateHashModel right) {
            this.left = left;
            this.right = right;
        }
        
        @Override
        public TemplateModel get(String key)
        throws TemplateModelException {
            TemplateModel model = right.get(key);
            return (model != null) ? model : left.get(key);
        }

        @Override
        public boolean isEmpty()
        throws TemplateModelException {
            return left.isEmpty() && right.isEmpty();
        }
    }

    private static final class ConcatenatedHashEx
    extends ConcatenatedHash
    implements TemplateHashModelEx {
        private CollectionAndSequence keys;
        private CollectionAndSequence values;

        ConcatenatedHashEx(TemplateHashModelEx left, TemplateHashModelEx right) {
            super(left, right);
        }
        
        @Override
        public int size() throws TemplateModelException {
            initKeys();
            return keys.size();
        }

        @Override
        public TemplateCollectionModel keys()
        throws TemplateModelException {
            initKeys();
            return keys;
        }

        @Override
        public TemplateCollectionModel values()
        throws TemplateModelException {
            initValues();
            return values;
        }

        private void initKeys()
        throws TemplateModelException {
            if (keys == null) {
                HashSet keySet = new HashSet();
                SimpleSequence keySeq = new SimpleSequence(32, _ObjectWrappers.SAFE_OBJECT_WRAPPER);
                addKeys(keySet, keySeq, (TemplateHashModelEx) this.left);
                addKeys(keySet, keySeq, (TemplateHashModelEx) this.right);
                keys = new CollectionAndSequence(keySeq);
            }
        }

        private static void addKeys(Set keySet, SimpleSequence keySeq, TemplateHashModelEx hash)
        throws TemplateModelException {
            TemplateModelIterator it = hash.keys().iterator();
            while (it.hasNext()) {
                TemplateScalarModel tsm = (TemplateScalarModel) it.next();
                if (keySet.add(tsm.getAsString())) {
                    // The first occurrence of the key decides the index;
                    // this is consistent with the behavior of java.util.LinkedHashSet.
                    keySeq.add(tsm);
                }
            }
        }        

        private void initValues()
        throws TemplateModelException {
            if (values == null) {
                SimpleSequence seq = new SimpleSequence(size(), _ObjectWrappers.SAFE_OBJECT_WRAPPER);
                // Note: size() invokes initKeys() if needed.
            
                int ln = keys.size();
                for (int i  = 0; i < ln; i++) {
                    seq.add(get(((TemplateScalarModel) keys.get(i)).getAsString()));
                }
                values = new CollectionAndSequence(seq);
            }
        }
    }
    
}
