/*
 * Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.jpql.tools.resolver;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.tools.NumericTypeComparator;
import org.eclipse.persistence.jpa.jpql.tools.TypeHelper;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeDeclaration;

/**
 * This {@link Resolver} is responsible to return the numeric type for a list of {@link Resolver
 * Resolvers}.
 * <p>
 * The result of a <b>CASE</b> expression, <b>COALESCE</b> expression, <b>NULLIF</b> expression, or
 * arithmetic expression (+, -, *, /) is determined by applying the following rule to its operands.
 * </p>
 * <ul>
 * <li>If there is an operand of type <code>Double</code> or <code>double</code>, the result of the
 *     operation is of type <code>Double</code>;
 * <li>otherwise, if there is an operand of type <code>Float</code> or <code>float</code>, the
 *     result of the operation is of type <code>Float</code>;
 * <li>otherwise, if there is an operand of type <code>BigDecimal</code>, the result of the
 *     operation is of type <code>BigDecimal</code>;
 * <li>otherwise, if there is an operand of type <code>BigInteger</code>, the result of the
 *     operation is of type <code>BigInteger</code>, unless the operator is / (division), in which
 *     case the numeric result type is not further defined;
 * <li>otherwise, if there is an operand of type <code>Long</code> or <code>long</code>, the result
 *     of the operation is of type <code>Long</code>, unless the operator is / (division), in which
 *     case the numeric result type is not further defined;
 * <li>otherwise, if there is an operand of integral type, the result of the operation is of type
 *     <code>Integer</code>, unless the operator is / (division), in which case the numeric result
 *     type is not further defined.
 * </ul>
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public class NumericResolver extends Resolver {

    /**
     * The {@link Resolver resolvers} used to calculate the numeric type.
     */
    private final Collection<Resolver> resolvers;

    /**
     * Creates a new <code>NumericResolver</code>.
     *
     * @param parent The parent {@link Resolver}, which is never <code>null</code>
     * @param typeResolvers The {@link Resolver resolvers} used to calculate the numeric type
     */
    public NumericResolver(Resolver parent, Collection<Resolver> typeResolvers) {
        super(parent);
        this.resolvers = typeResolvers;
    }

    /**
     * Creates a new <code>NumericResolver</code>.
     *
     * @param parent The parent {@link Resolver}, which is never <code>null</code>
     * @param resolver The {@link Resolver} used to calculate the numeric type
     */
    public NumericResolver(Resolver parent, Resolver resolver) {
        this(parent, Collections.singleton(resolver));
    }

    @Override
    protected IType buildType() {

        List<IType> types = new ArrayList<IType>(resolvers.size());
        TypeHelper helper = getTypeHelper();
        IType unresolvableType = helper.unknownType();

        // Convert any primitive types into its Class type and any non-number into Object
        for (Resolver typeResolver : resolvers) {

            IType type = typeResolver.getType();

            // Only a resolvable type will be added to the list
            if (type != unresolvableType) {
                // Non-numeric type cannot be added
                if (!helper.isNumericType(type)) {
                    type = helper.objectType();
                }
                types.add(type);
            }
        }

        if (types.isEmpty()) {
            return helper.unknownType();
        }

        // Comparing the types will result in putting the
        // result at the beginning of the list
        Collections.sort(types, new NumericTypeComparator(helper));

        return types.get(0);
    }

    @Override
    protected ITypeDeclaration buildTypeDeclaration() {
        return getType().getTypeDeclaration();
    }
}
