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

import freemarker.ext.beans.BeanModel;
import freemarker.ext.beans._BeansAPI;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;

/**
 * Internally used static utilities for evaluation expressions.
 */
class EvalUtil {
    static final int CMP_OP_EQUALS = 1;
    static final int CMP_OP_NOT_EQUALS = 2;
    static final int CMP_OP_LESS_THAN = 3;
    static final int CMP_OP_GREATER_THAN = 4;
    static final int CMP_OP_LESS_THAN_EQUALS = 5;
    static final int CMP_OP_GREATER_THAN_EQUALS = 6;
    // If you add a new operator here, update the "compare" and "cmpOpToString" methods!
    
    // Prevents instantination.
    private EvalUtil() { }
    
    /**
     * @param expr {@code null} is allowed, but may results in less helpful error messages
     * @param env {@code null} is allowed, but may results in lower performance in classic-compatible mode
     */
    static String modelToString(TemplateScalarModel model, Expression expr, Environment env)
    throws TemplateModelException {
        String value = model.getAsString();
        if (value == null) {
            if (env == null) env = Environment.getCurrentEnvironment();
            if (env != null && env.isClassicCompatible()) {
                return "";
            } else {
                throw newModelHasStoredNullException(String.class, model, expr);
            }
        }
        return value;
    }
    
    /**
     * @param expr {@code null} is allowed, but may results in less helpful error messages
     */
    static Number modelToNumber(TemplateNumberModel model, Expression expr)
        throws TemplateModelException {
        Number value = model.getAsNumber();
        if (value == null) throw newModelHasStoredNullException(Number.class, model, expr);
        return value;
    }

    /**
     * @param expr {@code null} is allowed, but may results in less helpful error messages
     */
    static Date modelToDate(TemplateDateModel model, Expression expr)
        throws TemplateModelException {
        Date value = model.getAsDate();
        if (value == null) throw newModelHasStoredNullException(Date.class, model, expr);
        return value;
    }
    
    /** Signals the buggy case where we have a non-null model, but it wraps a null. */
    static TemplateModelException newModelHasStoredNullException(
            Class expected, TemplateModel model, Expression expr) {
        return new _TemplateModelException(expr,
                _TemplateModelException.modelHasStoredNullDescription(expected, model));
    }

    /**
     * Compares two expressions according the rules of the FTL comparator operators.
     * 
     * @param leftExp not {@code null}
     * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}.
     * @param operatorString can be null {@code null}; the actual operator used, used for more accurate error message.
     * @param rightExp not {@code null}
     * @param env {@code null} is tolerated, but should be avoided
     */
    static boolean compare(
            Expression leftExp,
            int operator, String  operatorString,
            Expression rightExp,
            Expression defaultBlamed,
            Environment env) throws TemplateException {
        TemplateModel ltm = leftExp.eval(env);
        TemplateModel rtm = rightExp.eval(env);
        return compare(
                ltm, leftExp,
                operator, operatorString,
                rtm, rightExp,
                defaultBlamed, false,
                false, false, false,
                env);
    }
    
    /**
     * Compares values according the rules of the FTL comparator operators; if the {@link Expression}-s are
     * accessible, use {@link #compare(Expression, int, String, Expression, Expression, Environment)} instead, as
     * that gives better error messages.
     * 
     * @param leftValue maybe {@code null}, which will usually cause the appropriate {@link TemplateException}. 
     * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}.
     * @param rightValue maybe {@code null}, which will usually cause the appropriate {@link TemplateException}.
     * @param env {@code null} is tolerated, but should be avoided
     */
    static boolean compare(
            TemplateModel leftValue, int operator, TemplateModel rightValue,
            Environment env) throws TemplateException {
        return compare(
                leftValue, null,
                operator, null,
                rightValue, null,
                null, false,
                false, false, false,
                env);
    }

    /**
     * Same as {@link #compare(TemplateModel, int, TemplateModel, Environment)}, but if the two types are incompatible,
     *     they are treated as non-equal instead of throwing an exception. Comparing dates of different types will
     *     still throw an exception, however.
     */
    static boolean compareLenient(
            TemplateModel leftValue, int operator, TemplateModel rightValue,
            Environment env) throws TemplateException {
        return compare(
                leftValue, null,
                operator, null,
                rightValue, null,
                null, false,
                true, false, false,
                env);
    }
    
    private static final String VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE
            = "value of the comparison is a date-like value where "
              + "it's not known if it's a date (no time part), time, or date-time, "
              + "and thus can't be used in a comparison.";
    
    /**
     * @param leftExp {@code null} is allowed, but may results in less helpful error messages
     * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}.
     * @param operatorString can be null {@code null}; the actual operator used, used for more accurate error message.
     * @param rightExp {@code null} is allowed, but may results in less helpful error messages
     * @param defaultBlamed {@code null} allowed; the expression to which the error will point to if something goes
     *        wrong that is not specific to the left or right side expression, or if that expression is {@code null}.
     * @param typeMismatchMeansNotEqual If the two types are incompatible, they are treated as non-equal instead
     *     of throwing an exception. Comparing dates of different types will still throw an exception, however. 
     * @param leftNullReturnsFalse if {@code true}, a {@code null} left value will not cause exception, but make the
     *     expression {@code false}.  
     * @param rightNullReturnsFalse if {@code true}, a {@code null} right value will not cause exception, but make the
     *     expression {@code false}.  
     */
    static boolean compare(
            TemplateModel leftValue, Expression leftExp,
            int operator, String operatorString,
            TemplateModel rightValue, Expression rightExp,
            Expression defaultBlamed, boolean quoteOperandsInErrors,
            boolean typeMismatchMeansNotEqual,
            boolean leftNullReturnsFalse, boolean rightNullReturnsFalse,
            Environment env) throws TemplateException {
        if (leftValue == null) {
            if (env != null && env.isClassicCompatible()) {
                leftValue = TemplateScalarModel.EMPTY_STRING;
            } else {
                if (leftNullReturnsFalse) { 
                    return false;
                } else {
                    if (leftExp != null) {
                        throw InvalidReferenceException.getInstance(leftExp, env);
                    } else {
                        throw new _MiscTemplateException(defaultBlamed, env, 
                                    "The left operand of the comparison was undefined or null.");
                    }
                }
            }
        }

        if (rightValue == null) {
            if (env != null && env.isClassicCompatible()) {
                rightValue = TemplateScalarModel.EMPTY_STRING;
            } else {
                if (rightNullReturnsFalse) { 
                    return false;
                } else {
                    if (rightExp != null) {
                        throw InvalidReferenceException.getInstance(rightExp, env);
                    } else {
                        throw new _MiscTemplateException(defaultBlamed, env,
                                    "The right operand of the comparison was undefined or null.");
                    }
                }
            }
        }

        final int cmpResult;
        if (leftValue instanceof TemplateNumberModel && rightValue instanceof TemplateNumberModel) {
            Number leftNum = EvalUtil.modelToNumber((TemplateNumberModel) leftValue, leftExp);
            Number rightNum = EvalUtil.modelToNumber((TemplateNumberModel) rightValue, rightExp);
            ArithmeticEngine ae =
                    env != null
                        ? env.getArithmeticEngine()
                        : (leftExp != null
                            ? leftExp.getUnboundTemplate().getConfiguration().getArithmeticEngine()
                            : ArithmeticEngine.BIGDECIMAL_ENGINE);
            try {
                cmpResult = ae.compareNumbers(leftNum, rightNum);
            } catch (RuntimeException e) {
                throw new _MiscTemplateException(defaultBlamed, e, env, new Object[]
                        { "Unexpected error while comparing two numbers: ", e });
            }
        } else if (leftValue instanceof TemplateDateModel && rightValue instanceof TemplateDateModel) {
            TemplateDateModel leftDateModel = (TemplateDateModel) leftValue;
            TemplateDateModel rightDateModel = (TemplateDateModel) rightValue;
            
            int leftDateType = leftDateModel.getDateType();
            int rightDateType = rightDateModel.getDateType();
            
            if (leftDateType == TemplateDateModel.UNKNOWN || rightDateType == TemplateDateModel.UNKNOWN) {
                String sideName;
                Expression sideExp;
                if (leftDateType == TemplateDateModel.UNKNOWN) {
                    sideName = "left";
                    sideExp = leftExp;
                } else {
                    sideName = "right";
                    sideExp = rightExp;
                }
                
                throw new _MiscTemplateException(sideExp != null ? sideExp : defaultBlamed, env,
                        "The ", sideName, " ", VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE);
            }
            
            if (leftDateType != rightDateType) {
                ;
                throw new _MiscTemplateException(defaultBlamed, env,
                        "Can't compare dates of different types. Left date type is ",
                        TemplateDateModel.TYPE_NAMES.get(leftDateType), ", right date type is ",
                        TemplateDateModel.TYPE_NAMES.get(rightDateType), ".");
            }

            Date leftDate = EvalUtil.modelToDate(leftDateModel, leftExp);
            Date rightDate = EvalUtil.modelToDate(rightDateModel, rightExp);
            cmpResult = leftDate.compareTo(rightDate);
        } else if (leftValue instanceof TemplateScalarModel && rightValue instanceof TemplateScalarModel) {
            if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) {
                throw new _MiscTemplateException(defaultBlamed, env,
                        "Can't use operator \"", cmpOpToString(operator, operatorString), "\" on string values.");
            }
            String leftString = EvalUtil.modelToString((TemplateScalarModel) leftValue, leftExp, env);
            String rightString = EvalUtil.modelToString((TemplateScalarModel) rightValue, rightExp, env);
            // FIXME NBC: Don't use the Collator here. That's locale-specific, but ==/!= should not be.
            cmpResult = env.getCollator().compare(leftString, rightString);
        } else if (leftValue instanceof TemplateBooleanModel && rightValue instanceof TemplateBooleanModel) {
            if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) {
                throw new _MiscTemplateException(defaultBlamed, env,
                        "Can't use operator \"", cmpOpToString(operator, operatorString), "\" on boolean values.");
            }
            boolean leftBool = ((TemplateBooleanModel) leftValue).getAsBoolean();
            boolean rightBool = ((TemplateBooleanModel) rightValue).getAsBoolean();
            cmpResult = (leftBool ? 1 : 0) - (rightBool ? 1 : 0);
        } else if (env.isClassicCompatible()) {
            String leftSting = leftExp.evalAndCoerceToPlainText(env);
            String rightString = rightExp.evalAndCoerceToPlainText(env);
            cmpResult = env.getCollator().compare(leftSting, rightString);
        } else {
            if (typeMismatchMeansNotEqual) {
                if (operator == CMP_OP_EQUALS) {
                    return false;
                } else if (operator == CMP_OP_NOT_EQUALS) {
                    return true;
                }
                // Falls through
            }
            throw new _MiscTemplateException(defaultBlamed, env,
                    "Can't compare values of these types. ",
                    "Allowed comparisons are between two numbers, two strings, two dates, or two booleans.\n",
                    "Left hand operand ",
                    (quoteOperandsInErrors && leftExp != null
                            ? new Object[] { "(", new _DelayedGetCanonicalForm(leftExp), ") value " }
                            : (Object) ""),
                    "is ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(leftValue)), ".\n",
                    "Right hand operand ",
                    (quoteOperandsInErrors && rightExp != null
                            ? new Object[] { "(", new _DelayedGetCanonicalForm(rightExp), ") value " }
                            : (Object) ""),
                    "is ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(rightValue)),
                    ".");
        }

        switch (operator) {
            case CMP_OP_EQUALS: return cmpResult == 0;
            case CMP_OP_NOT_EQUALS: return cmpResult != 0;
            case CMP_OP_LESS_THAN: return cmpResult < 0;
            case CMP_OP_GREATER_THAN: return cmpResult > 0;
            case CMP_OP_LESS_THAN_EQUALS: return cmpResult <= 0;
            case CMP_OP_GREATER_THAN_EQUALS: return cmpResult >= 0;
            default: throw new BugException("Unsupported comparator operator code: " + operator);
        }
    }

    private static String cmpOpToString(int operator, String operatorString) {
        if (operatorString != null) {
            return operatorString;
        } else {
            switch (operator) {
                case CMP_OP_EQUALS: return "equals";
                case CMP_OP_NOT_EQUALS: return "not-equals";
                case CMP_OP_LESS_THAN: return "less-than";
                case CMP_OP_GREATER_THAN: return "greater-than";
                case CMP_OP_LESS_THAN_EQUALS: return "less-than-equals";
                case CMP_OP_GREATER_THAN_EQUALS: return "greater-than-equals";
                default: return "???";
            }
        }
    }

    /**
     * Converts a value to plain text {@link String}, or a {@link TemplateMarkupOutputModel} if that's what the
     * {@link TemplateValueFormat} involved produces.
     * 
     * @param seqTip
     *            Tip to display if the value type is not coercable, but it's sequence or collection.
     * 
     * @return Never {@code null}
     */
    static Object coerceModelToStringOrMarkup(TemplateModel tm, Expression exp, String seqTip, Environment env)
            throws TemplateException {
        if (tm instanceof TemplateNumberModel) {
            TemplateNumberModel tnm = (TemplateNumberModel) tm; 
            TemplateNumberFormat format = env.getTemplateNumberFormat(exp, false);
            try {
                return assertFormatResultNotNull(format.format(tnm));
            } catch (TemplateValueFormatException e) {
                throw MessageUtil.newCantFormatNumberException(format, exp, e, false);
            }
        } else if (tm instanceof TemplateDateModel) {
            TemplateDateModel tdm = (TemplateDateModel) tm;
            TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, false);
            try {
                return assertFormatResultNotNull(format.format(tdm));
            } catch (TemplateValueFormatException e) {
                throw MessageUtil.newCantFormatDateException(format, exp, e, false);
            }
        } else if (tm instanceof TemplateMarkupOutputModel) {
            return tm;
        } else { 
            return coerceModelToTextualCommon(tm, exp, seqTip, true, env);
        }
    }

    /**
     * Like {@link #coerceModelToStringOrMarkup(TemplateModel, Expression, String, Environment)}, but gives error
     * if the result is markup. This is what you normally use where markup results can't be used.
     *
     * @param seqTip
     *            Tip to display if the value type is not coercable, but it's sequence or collection.
     * 
     * @return Never {@code null}
     */
    static String coerceModelToStringOrUnsupportedMarkup(
            TemplateModel tm, Expression exp, String seqTip, Environment env)
            throws TemplateException {
        if (tm instanceof TemplateNumberModel) {
            TemplateNumberModel tnm = (TemplateNumberModel) tm; 
            TemplateNumberFormat format = env.getTemplateNumberFormat(exp, false);
            try {
                return ensureFormatResultString(format.format(tnm), exp, env);
            } catch (TemplateValueFormatException e) {
                throw MessageUtil.newCantFormatNumberException(format, exp, e, false);
            }
        } else if (tm instanceof TemplateDateModel) {
            TemplateDateModel tdm = (TemplateDateModel) tm;
            TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, false);
            try {
                return ensureFormatResultString(format.format(tdm), exp, env);
            } catch (TemplateValueFormatException e) {
                throw MessageUtil.newCantFormatDateException(format, exp, e, false);
            }
        } else { 
            return coerceModelToTextualCommon(tm, exp, seqTip, false, env);
        }
    }

    /**
     * Converts a value to plain text {@link String}, even if the {@link TemplateValueFormat} involved normally produces
     * markup. This should be used rarely, where the user clearly intend to use the plain text variant of the format.
     * 
     * @param seqTip
     *            Tip to display if the value type is not coercable, but it's sequence or collection.
     * 
     * @return Never {@code null}
     */
    static String coerceModelToPlainText(TemplateModel tm, Expression exp, String seqTip,
            Environment env) throws TemplateException {
        if (tm instanceof TemplateNumberModel) {
            return assertFormatResultNotNull(env.formatNumberToPlainText((TemplateNumberModel) tm, exp, false));
        } else if (tm instanceof TemplateDateModel) {
            return assertFormatResultNotNull(env.formatDateToPlainText((TemplateDateModel) tm, exp, false));
        } else {
            return coerceModelToTextualCommon(tm, exp, seqTip, false, env);
        }
    }

    /**
     * @param tm
     *            If {@code null} that's an exception, unless we are in classic compatible mode.
     * 
     * @param supportsTOM
     *            Whether the caller {@code coerceModelTo...} method could handle a {@link TemplateMarkupOutputModel}.
     *            
     * @return Never {@code null}
     */
    private static String coerceModelToTextualCommon(
            TemplateModel tm, Expression exp, String seqHint, boolean supportsTOM, Environment env)
            throws TemplateModelException, InvalidReferenceException, TemplateException,
                    NonStringOrTemplateOutputException, NonStringException {
        if (tm instanceof TemplateScalarModel) {
            return modelToString((TemplateScalarModel) tm, exp, env);
        } else if (tm == null) {
            if (env.isClassicCompatible()) {
                return "";
            } else {
                if (exp != null) {
                    throw InvalidReferenceException.getInstance(exp, env);
                } else {
                    throw new InvalidReferenceException(
                            "Null/missing value (no more informatoin avilable)",
                            env);
                }
            }
        } else if (tm instanceof TemplateBooleanModel) {
            // This should be before TemplateScalarModel, but automatic boolean-to-string is only non-error since 2.3.20
            // (and before that when classic_compatible was true), so to keep backward compatibility we couldn't insert
            // this before TemplateScalarModel.
            boolean booleanValue = ((TemplateBooleanModel) tm).getAsBoolean();
            int compatMode = env.getClassicCompatibleAsInt();
            if (compatMode == 0) {
                return env.formatBoolean(booleanValue, false);
            } else {
                if (compatMode == 1) {
                    return booleanValue ? MiscUtil.C_TRUE : "";
                } else if (compatMode == 2) {
                    if (tm instanceof BeanModel) {
                        // In 2.1, bean-wrapped booleans where strings, so that has overridden the boolean behavior: 
                        return _BeansAPI.getAsClassicCompatibleString((BeanModel) tm);
                    } else {
                        return booleanValue ? MiscUtil.C_TRUE : "";
                    }
                } else {
                    throw new BugException("Unsupported classic_compatible variation: " + compatMode);
                }
            }
        } else {
            if (env.isClassicCompatible() && tm instanceof BeanModel) {
                return _BeansAPI.getAsClassicCompatibleString((BeanModel) tm);
            }
            if (seqHint != null && (tm instanceof TemplateSequenceModel || tm instanceof TemplateCollectionModel)) {
                if (supportsTOM) {
                    throw new NonStringOrTemplateOutputException(exp, tm, seqHint, env);
                } else {
                    throw new NonStringException(exp, tm, seqHint, env);
                }
            } else {
                if (supportsTOM) {
                    throw new NonStringOrTemplateOutputException(exp, tm, env);
                } else {
                    throw new NonStringException(exp, tm, env);
                }
            }
        }
    }

    private static String ensureFormatResultString(Object formatResult, Expression exp, Environment env)
            throws NonStringException {
        if (formatResult instanceof String) { 
            return (String) formatResult;
        }
        
        assertFormatResultNotNull(formatResult);
        
        TemplateMarkupOutputModel mo = (TemplateMarkupOutputModel) formatResult;
        _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder(
                "Value was formatted to convert it to string, but the result was markup of ouput format ",
                new _DelayedJQuote(mo.getOutputFormat()), ".")
                .tip("Use value?string to force formatting to plain text.")
                .blame(exp);
        throw new NonStringException(null, desc);
    }

    static String assertFormatResultNotNull(String r) {
        if (r != null) {
            return r;
        }
        throw new NullPointerException("TemplateValueFormatter result can't be null");
    }

    static Object assertFormatResultNotNull(Object r) {
        if (r != null) {
            return r;
        }
        throw new NullPointerException("TemplateValueFormatter result can't be null");
    }

    static TemplateMarkupOutputModel concatMarkupOutputs(TemplateObject parent, TemplateMarkupOutputModel leftMO,
            TemplateMarkupOutputModel rightMO) throws TemplateException {
        MarkupOutputFormat leftOF = leftMO.getOutputFormat();
        MarkupOutputFormat rightOF = rightMO.getOutputFormat();
        if (rightOF != leftOF) {
            String rightPT;
            String leftPT;
            if ((rightPT = rightOF.getSourcePlainText(rightMO)) != null) {
                return leftOF.concat(leftMO, leftOF.fromPlainTextByEscaping(rightPT));
            } else if ((leftPT = leftOF.getSourcePlainText(leftMO)) != null) {
                return rightOF.concat(rightOF.fromPlainTextByEscaping(leftPT), rightMO);
            } else {
                Object[] message = { "Concatenation left hand operand is in ", new _DelayedToString(leftOF),
                        " format, while the right hand operand is in ", new _DelayedToString(rightOF),
                        ". Conversion to common format wasn't possible." };
                if (parent instanceof Expression) {
                    throw new _MiscTemplateException((Expression) parent, message);
                } else {
                    throw new _MiscTemplateException(message);
                }
            }
        } else {
            return leftOF.concat(leftMO, rightMO);
        }
    }

    /**
     * Returns an {@link ArithmeticEngine} even if {@code env} is {@code null}, because we are in parsing phase.
     */
    static ArithmeticEngine getArithmeticEngine(Environment env, TemplateObject tObj) {
        return env != null
                ? env.getArithmeticEngine()
                : tObj.getUnboundTemplate().getParserConfiguration().getArithmeticEngine();
    }
    
}
