/*
 * Copyright (c) 1998, 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 from Oracle TopLink
//     10/01/2018: Will Dazey
//       - #253: Add support for embedded constructor results with CriteriaBuilder
package org.eclipse.persistence.queries;

import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.StringHelper;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.mappings.DatabaseMapping;


/**
 * <b>Purpose</b>: An item specifying a class constructor method to be used in a ReportQuery's returned results.
 * <p>Example:
 * <blockquote><pre>
 *      ConstructorReportItem item = new ConstructorReportItem("Employee");
 *      item.setResultType(Employee.class);
 *      item.addAttribute("firstName", employees.get("firstName"));
 *      query.addConstructorReportItem(item);
 * </pre></blockquote>
 * <p>
 * When executed will return a collection of ReportQueryResults that contain Employee objects created using
 * the new Employee(firstname) constructor.
 *
 * @author Chris Delahunt
 * @since TopLink Essentials 1.0
 */
public class ConstructorReportItem extends ReportItem  {

    /**
     * String prefix of {@link #toString()} output.
     */
    private static final String TO_STR_PREFIX = "ConstructorReportItem(";

    /**
     * String to separate name and items array of {@link #toString()} output.
     */
    private static final String TO_STR_ARRAY = " -> [";

    /**
     * String suffix of {@link #toString()} output.
     */
    private static final String TO_STR_SUFFIX = "])";

    protected Class[] constructorArgTypes;
    protected List<DatabaseMapping> constructorMappings;
    protected List<ReportItem> reportItems;
    protected Constructor constructor;

    /**
     * Create a new constructor item.
     */
    public ConstructorReportItem() {
    }

    /**
     * Create a new constructor item.
     * @param name string used to look up this result in the ReportQueryResult.
     */
    public ConstructorReportItem(String name) {
        super(name, null);
    }

    /**
     * Method to add an expression to be used to return the parameter that is then passed into the constructor method.
     * Similar to ReportQuery's addAttribute method, but name is not needed.
     */
    public void addAttribute(Expression attributeExpression) {
        ReportItem item = new ReportItem(getName()+getReportItems().size(), attributeExpression);
        getReportItems().add(item);
    }

    /**
     * Add the attribute with joining.
     */
    public void addAttribute(String attributeName, Expression attributeExpression, List joinedExpressions) {
        ReportItem item = new ReportItem(attributeName, attributeExpression);
        item.getJoinedAttributeManager().setJoinedAttributeExpressions_(joinedExpressions);
        getReportItems().add(item);
    }

    public void addItem(ReportItem item) {
        getReportItems().add(item);
    }

    public Class[] getConstructorArgTypes(){
        return constructorArgTypes;
    }

    /**
     * INTERNAL:
     * Return the mappings for the items.
     */
    public List<DatabaseMapping> getConstructorMappings(){
        return constructorMappings;
    }

    /**
     * INTERNAL:
     * Return the constructor.
     */
    public Constructor getConstructor(){
        return constructor;
    }

    /**
     * INTERNAL:
     * Set the constructor.
     */
    public void setConstructor(Constructor constructor){
        this.constructor = constructor;
    }

    public List<ReportItem> getReportItems(){
        if (reportItems == null) {
            reportItems = new ArrayList<>();
        }
        return reportItems;
    }

    /**
     * INTERNAL:
     * Looks up mapping for attribute during preExecute of ReportQuery
     */
    @Override
    public void initialize(ReportQuery query) throws QueryException {
        int size= getReportItems().size();
        List<DatabaseMapping> mappings = new ArrayList<>();
        for (int index = 0; index < size; index++) {
            ReportItem item = reportItems.get(index);
            item.initialize(query);
            mappings.add(item.getMapping());
        }
        setConstructorMappings(mappings);

        int numberOfItems = getReportItems().size();
        // Arguments may be initialized depending on how the query was constructed, so types may be undefined though.
        if (getConstructorArgTypes() == null) {
            setConstructorArgTypes(new Class[numberOfItems]);
        }
        Class[] constructorArgTypes = getConstructorArgTypes();
        for (int index = 0; index < numberOfItems; index++) {
            if (constructorArgTypes[index] == null) {
                ReportItem argumentItem = getReportItems().get(index);
                if (mappings.get(index) != null) {
                    DatabaseMapping mapping = constructorMappings.get(index);
                    if (argumentItem.getAttributeExpression() != null && argumentItem.getAttributeExpression().isMapEntryExpression()){
                        if (((MapEntryExpression)argumentItem.getAttributeExpression()).shouldReturnMapEntry()){
                            constructorArgTypes[index] = Map.Entry.class;
                        } else {
                            constructorArgTypes[index] = (Class) mapping.getContainerPolicy().getKeyType();
                        }
                    } else {
                        constructorArgTypes[index] = mapping.getAttributeClassification();
                    }
                } else if (argumentItem.getResultType() != null) {
                    constructorArgTypes[index] = argumentItem.getResultType();
                } else if (argumentItem.getDescriptor() != null) {
                    constructorArgTypes[index] = argumentItem.getDescriptor().getJavaClass();
                } else if (argumentItem.getAttributeExpression() != null && argumentItem.getAttributeExpression().isConstantExpression()){
                    constructorArgTypes[index] = ((ConstantExpression)argumentItem.getAttributeExpression()).getValue().getClass();
                } else {
                    // Use Object.class by default.
                    constructorArgTypes[index] = ClassConstants.OBJECT;
                }
            }
        }
        if (getConstructor() == null) {
            try {
                Constructor constructor = null;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<Class<?>>(getResultType(), constructorArgTypes, true));
                    } catch (PrivilegedActionException exception) {
                        throw QueryException.exceptionWhileUsingConstructorExpression(exception.getException(), query);
                    }
                } else {
                    constructor = PrivilegedAccessHelper.getConstructorFor(getResultType(), constructorArgTypes, true);
                }
                setConstructor(constructor);
            } catch (NoSuchMethodException exception) {
                throw QueryException.exceptionWhileUsingConstructorExpression(exception, query);
            }
        }
    }

    @Override
    public boolean isConstructorItem(){
        return true;
    }

    public void setConstructorArgTypes(Class[] constructorArgTypes){
        this.constructorArgTypes = constructorArgTypes;
    }

    /**
     * INTERNAL:
     * Return the mappings for the items.
     */
    public void setConstructorMappings(List<DatabaseMapping> constructorMappings){
        this.constructorMappings = constructorMappings;
    }

    public void setReportItems(List<ReportItem> reportItems){
        this.reportItems = reportItems;
    }

    @Override
    public String toString() {
        String name = StringHelper.nonNullString(getName());
        // Calculate string length
        int length = TO_STR_PREFIX.length() + name.length()
                + TO_STR_ARRAY.length() + TO_STR_SUFFIX.length();
        int size = reportItems != null ? reportItems.size() : 0;
        String[] items = new String[size];
        for (int i=0; i < size; i++) {
            items[i] = StringHelper.nonNullString(reportItems.get(i).toString());
            length += items[i].length();
        }
        // Build string
        StringBuilder str = new StringBuilder(length);
        str.append(TO_STR_PREFIX).append(name).append(TO_STR_ARRAY);
        for (int i=0; i < size; i++) {
            str.append(items[i]);
        }
        str.append(TO_STR_SUFFIX);
        return str.toString();
    }

}
