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

import freemarker.template.SimpleScalar;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.utility.StringUtil;

final class StringLiteral extends Expression implements TemplateScalarModel {
    
    private final String value;
    
    /** {@link List} of {@link String}-s and {@link Interpolation}-s. */
    private List<Object> dynamicValue;
    
    StringLiteral(String value) {
        this.value = value;
    }
    
    /**
     * @param parentTkMan
     *            The token source of the template that contains this string literal. As of this writing, we only need
     *            this to share the {@code namingConvetion} with that.
     */
    void parseValue(FMParserTokenManager parentTkMan, OutputFormat outputFormat) throws ParseException {
        // The way this work is incorrect (the literal should be parsed without un-escaping),
        // but we can't fix this backward compatibly.
        if (value.length() > 3 && (value.indexOf("${") >= 0 || value.indexOf("#{") >= 0)) {
            
            Template parentTemplate = getTemplate();

            try {
                FMParserTokenManager tkMan = new FMParserTokenManager(
                        new SimpleCharStream(
                                new StringReader(value),
                                beginLine, beginColumn + 1,
                                value.length()));
                
                FMParser parser = new FMParser(parentTemplate, false, tkMan, parentTemplate.getParserConfiguration());
                // We continue from the parent parser's current state:
                parser.setupStringLiteralMode(parentTkMan, outputFormat);
                try {
                    dynamicValue = parser.StaticTextAndInterpolations();
                } finally {
                    // The parent parser continues from this parser's current state:
                    parser.tearDownStringLiteralMode(parentTkMan);
                }
            } catch (ParseException e) {
                e.setTemplateName(parentTemplate.getSourceName());
                throw e;
            }
            this.constantValue = null;
        }
    }
    
    @Override
    TemplateModel _eval(Environment env) throws TemplateException {
        if (dynamicValue == null) {
            return new SimpleScalar(value);
        } else {
            // This should behave like concatenating the values with `+`. Thus, an interpolated expression that
            // returns markup promotes the result of the whole expression to markup.
            
            // Exactly one of these is non-null, depending on if the result will be plain text or markup, which can
            // change during evaluation, depending on the result of the interpolations:
            StringBuilder plainTextResult = null;
            TemplateMarkupOutputModel<?> markupResult = null;
            
            for (Object part : dynamicValue) {
                Object calcedPart =
                        part instanceof String ? part
                        : ((Interpolation) part).calculateInterpolatedStringOrMarkup(env);
                if (markupResult != null) {
                    TemplateMarkupOutputModel<?> partMO = calcedPart instanceof String
                            ? markupResult.getOutputFormat().fromPlainTextByEscaping((String) calcedPart)
                            : (TemplateMarkupOutputModel<?>) calcedPart;
                    markupResult = EvalUtil.concatMarkupOutputs(this, markupResult, partMO);
                } else { // We are using `plainTextOutput` (or nothing yet)
                    if (calcedPart instanceof String) {
                        String partStr = (String) calcedPart;
                        if (plainTextResult == null) {
                            plainTextResult = new StringBuilder(partStr);
                        } else {
                            plainTextResult.append(partStr);
                        }
                    } else { // `calcedPart` is TemplateMarkupOutputModel
                        TemplateMarkupOutputModel<?> moPart = (TemplateMarkupOutputModel<?>) calcedPart;
                        if (plainTextResult != null) {
                            TemplateMarkupOutputModel<?> leftHandMO = moPart.getOutputFormat()
                                    .fromPlainTextByEscaping(plainTextResult.toString());
                            markupResult = EvalUtil.concatMarkupOutputs(this, leftHandMO, moPart);
                            plainTextResult = null;
                        } else {
                            markupResult = moPart;
                        }
                    }
                }
            } // for each part
            return markupResult != null ? markupResult
                    : plainTextResult != null ? new SimpleScalar(plainTextResult.toString())
                    : SimpleScalar.EMPTY_STRING;
        }
    }

    public String getAsString() {
        return value;
    }
    
    /**
     * Tells if this is something like <tt>"${foo}"</tt>, which is usually a user mistake.
     */
    boolean isSingleInterpolationLiteral() {
        return dynamicValue != null && dynamicValue.size() == 1
                && dynamicValue.get(0) instanceof Interpolation;
    }
    
    @Override
    public String getCanonicalForm() {
        if (dynamicValue == null) {
            return StringUtil.ftlQuote(value);
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append('"');
            for (Object child : dynamicValue) {
                if (child instanceof Interpolation) {
                    sb.append(((Interpolation) child).getCanonicalFormInStringLiteral());
                } else {
                    sb.append(StringUtil.FTLStringLiteralEnc((String) child, '"'));
                }
            }
            sb.append('"');
            return sb.toString();
        }
    }
    
    @Override
    String getNodeTypeSymbol() {
        return dynamicValue == null ? getCanonicalForm() : "dynamic \"...\"";
    }
    
    @Override
    boolean isLiteral() {
        return dynamicValue == null;
    }

    @Override
    protected Expression deepCloneWithIdentifierReplaced_inner(
            String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) {
        StringLiteral cloned = new StringLiteral(value);
        // FIXME: replacedIdentifier should be searched inside interpolatedOutput too:
        cloned.dynamicValue = this.dynamicValue;
        return cloned;
    }

    @Override
    int getParameterCount() {
        return dynamicValue == null ? 0 : dynamicValue.size();
    }

    @Override
    Object getParameterValue(int idx) {
        checkIndex(idx);
        return dynamicValue.get(idx);
    }

    private void checkIndex(int idx) {
        if (dynamicValue == null || idx >= dynamicValue.size()) {
            throw new IndexOutOfBoundsException();
        }
    }

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