/*
 * 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 freemarker.template.SimpleNumber;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;

/**
 * An operator for arithmetic operations. Note that the + operator is in {@link AddConcatExpression}, because its
 * overloaded (does string concatenation and more).
 */
final class ArithmeticExpression extends Expression {

    static final int TYPE_SUBSTRACTION = 0;
    static final int TYPE_MULTIPLICATION = 1;
    static final int TYPE_DIVISION = 2;
    static final int TYPE_MODULO = 3;

    private static final char[] OPERATOR_IMAGES = new char[] { '-', '*', '/', '%' };

    private final Expression lho;
    private final Expression rho;
    private final int operator;

    ArithmeticExpression(Expression lho, Expression rho, int operator) {
        this.lho = lho;
        this.rho = rho;
        this.operator = operator;
    }

    @Override
    TemplateModel _eval(Environment env) throws TemplateException {
        return _eval(env, this, lho.evalToNumber(env), operator, rho.evalToNumber(env));
    }

    static TemplateModel _eval(Environment env, TemplateObject parent, Number lhoNumber, int operator, Number rhoNumber)
            throws TemplateException, _MiscTemplateException {
        ArithmeticEngine ae = EvalUtil.getArithmeticEngine(env, parent); 
        switch (operator) {
            case TYPE_SUBSTRACTION : 
                return new SimpleNumber(ae.subtract(lhoNumber, rhoNumber));
            case TYPE_MULTIPLICATION :
                return new SimpleNumber(ae.multiply(lhoNumber, rhoNumber));
            case TYPE_DIVISION :
                return new SimpleNumber(ae.divide(lhoNumber, rhoNumber));
            case TYPE_MODULO :
                return new SimpleNumber(ae.modulus(lhoNumber, rhoNumber));
            default:
                if (parent instanceof Expression) {
                    throw new _MiscTemplateException((Expression) parent,
                            "Unknown operation: ", Integer.valueOf(operator));
                } else {
                    throw new _MiscTemplateException("Unknown operation: ", Integer.valueOf(operator));
                }
        }
    }

    @Override
    public String getCanonicalForm() {
        return lho.getCanonicalForm() + ' ' + getOperatorSymbol(operator) + ' ' + rho.getCanonicalForm();
    }
    
    @Override
    String getNodeTypeSymbol() {
        return String.valueOf(getOperatorSymbol(operator));
    }

    static char getOperatorSymbol(int operator) {
        return OPERATOR_IMAGES[operator];
    }
    
    @Override
    boolean isLiteral() {
        return constantValue != null || (lho.isLiteral() && rho.isLiteral());
    }

    @Override
    protected Expression deepCloneWithIdentifierReplaced_inner(
            String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) {
    	return new ArithmeticExpression(
    	        lho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState),
    	        rho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState),
    	        operator);
    }
    
    @Override
    int getParameterCount() {
        return 3;
    }

    @Override
    Object getParameterValue(int idx) {
        switch (idx) {
        case 0: return lho;
        case 1: return rho;
        case 2: return Integer.valueOf(operator);
        default: throw new IndexOutOfBoundsException();
        }
    }

    @Override
    ParameterRole getParameterRole(int idx) {
        switch (idx) {
        case 0: return ParameterRole.LEFT_HAND_OPERAND;
        case 1: return ParameterRole.RIGHT_HAND_OPERAND;
        case 2: return ParameterRole.AST_NODE_SUBTYPE;
        default: throw new IndexOutOfBoundsException();
        }
    }
    
}
