/*
 * 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
//     08/01/2012-2.5 Chris Delahunt
//       - 371950: Metadata caching
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/11/2012-2.5 Guy Pelletier
//       - 393867: Named queries do not work when using EM level Table Per Tenant Multitenancy.
package org.eclipse.persistence.internal.jpa;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractSession;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import jakarta.persistence.LockModeType;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.EntityResult;
import org.eclipse.persistence.queries.SQLResultSetMapping;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.Session;

/**
 * <b>Purpose</b>:
 * A JPA placeholder Query object to store JPQL strings so that processing the string is delayed
 * until Login.
 *
 * @author Chris Delahunt
 * @since TopLink Essentials
 */
public class JPAQuery extends DatabaseQuery  {
    private String lockMode;
    private String jpqlString;
    private String sqlString;
    private StoredProcedureCall call;
    private String resultClassName;
    private List<String> resultClassNames;
    private List<String> resultSetMappingNames;
    private Map<String, Object> hints;

    public JPAQuery() {
    }

    public JPAQuery(String jpqlString) {
        this.jpqlString=jpqlString;
    }

    /**
     * JPQL
     */
    public JPAQuery(String name, String jpqlString, String lockMode, Map<String, Object> hints) {
        this.name = name;
        this.jpqlString = jpqlString;
        this.flushOnExecute = null;
        this.hints = hints;
        this.lockMode = lockMode;
        if (lockMode == null) {
            this.lockMode = "NONE";
        }
    }

    /*
     * SQL returning an entity
     */
    public JPAQuery(String queryName, String sqlString, Map<String, Object> hints) {
        this.name = queryName;
        this.sqlString = sqlString;
        this.flushOnExecute = null;
        this.hints = hints;
        this.lockMode = null;
    }

    /*
     * Stored Proc returning an Entity
     */
    public JPAQuery(String queryName, StoredProcedureCall call, Map<String, Object> hints) {
        this.name = queryName;
        this.call = call;
        this.flushOnExecute = null;
        this.hints = hints;
        this.lockMode = null;
    }

    public void addResultClassNames(String className) {
        if (resultClassNames == null) {
            resultClassNames = new ArrayList<>();
        }
        this.resultClassNames.add(className);
    }

    public void addResultSetMapping(String resultSetMapping){
        if (resultSetMappingNames == null) {
            resultSetMappingNames = new ArrayList<>();
        }
        this.resultSetMappingNames.add(resultSetMapping);
    }

    /**
     * INTERNAL:
     * This should never be called and is only here because it is needed as an extension
     * to DatabaseQuery.  Perhaps exception should be thrown to warn users, but for now
     * it will execute the resulting query instead, this allows JPA style queries to be executed
     * on a normal EclipseLink Session.
     */
    @Override
    public Object executeDatabaseQuery() throws DatabaseException, OptimisticLockException{
        return getSession().executeQuery(getDatabaseQuery());
    }

    public DatabaseQuery getDatabaseQuery() {
        return (DatabaseQuery)getProperty("databasequery");
    }

    /**
     * INTERNAL:
     * For table per tenant queries the descriptor list will extracted from
     * parsing the jpql query and cached here.
     */
    @Override
    public List<ClassDescriptor> getDescriptors() {
        return descriptors;
    }

    /**
     * Return the JPA query hints.
     */
    public Map<String, Object> getHints(){
        return hints;
    }

    /**
     * Return the JPQL string.
     */
    @Override
    public String getJPQLString(){
        return jpqlString;
    }

    /**
     * Return true if this query is a jpql query.
     */
    public boolean isJPQLQuery() {
        return jpqlString != null;
    }

    /**
     * Return true if this query is an sql query.
     */
    public boolean isSQLQuery() {
        return sqlString != null;
    }

    /**
     * INTERNAL:
     * Generate the DatabaseQuery query from the JPA named query.
     */
    @Override
    public void prepare() {
        DatabaseQuery query = null;
        ClassLoader loader = session.getDatasourcePlatform().getConversionManager().getLoader();

        if (isSQLQuery()) {
            query = processSQLQuery(getSession());
        } else if (isJPQLQuery()) {
            query = processJPQLQuery(getSession());
        } else if (call != null) {
            query = processStoredProcedureQuery(getSession());
            if (call.hasParameters() ) {
                //convert the type in the parameters;  query.convertClassNamesToClasses does not cascade to the call
                for (Object value: call.getParameters()) {
                    if (value instanceof Object[]) {
                        //must be inout type, and the out portion is a DatabaseField
                        ((DatabaseField) ((Object[])value)[1]).convertClassNamesToClasses(loader);
                        value =  ((Object[])value)[0];
                    }
                    if (value instanceof DatabaseField) {
                        ((DatabaseField) value).convertClassNamesToClasses(loader);
                    }
                }
            }
        }

        // Make sure all class names have been converted.
        query.convertClassNamesToClasses(loader);

        setDatabaseQuery(query);
    }

    /**
     * INTERNAL:
     * Convert the JPA query into a DatabaseQuery.
     */
    public DatabaseQuery processJPQLQuery(Session session){
        ClassLoader classloader = session.getDatasourcePlatform().getConversionManager().getLoader();
        LockModeType lockModeEnum = null;

        // Must handle errors if a JPA 2.0 option is used in JPA 1.0.
        try {
            lockModeEnum = LockModeType.valueOf(lockMode);
        } catch (Exception ignore) {
            // Ignore JPA 2.0 in JPA 1.0, reverts to no lock.
        }

        DatabaseQuery ejbquery = EJBQueryImpl.buildEJBQLDatabaseQuery(getName(), jpqlString, (AbstractSession) session, lockModeEnum, hints, classloader);
        ejbquery.setName(getName());

        return ejbquery;
    }

    /**
     * INTERNAL:
     * Convert the SQL string into a DatabaseQuery.
     */
    public DatabaseQuery processSQLQuery(Session session){
        DatabaseQuery query = null;
        ClassLoader loader = session.getDatasourcePlatform().getConversionManager().getLoader();

        if (resultClassName != null) {
            Class<?> clazz = session.getDatasourcePlatform().getConversionManager().convertClassNameToClass(resultClassName);
            query = EJBQueryImpl.buildSQLDatabaseQuery(clazz, sqlString, hints, loader, (AbstractSession)session);
        } else if (resultSetMappingNames != null) {
            query = EJBQueryImpl.buildSQLDatabaseQuery(resultSetMappingNames.get(0), sqlString, hints, loader, (AbstractSession)session);
        } else {
            // Neither a resultClass or resultSetMapping is specified so place in a temp query on the session
            query = EJBQueryImpl.buildSQLDatabaseQuery(sqlString, hints, loader, (AbstractSession)session);
        }

        query.setName(this.getName());
        return query;
    }

    /**
     * INTERNAL:
     * Convert the StoredProc call into a DatabaseQuery.
     */
    public DatabaseQuery processStoredProcedureQuery(Session session){
        DatabaseQuery query = null;
        ClassLoader loader = session.getDatasourcePlatform().getConversionManager().getLoader();

        if (resultClassNames != null) {
            List<SQLResultSetMapping> resultSetMappings = new ArrayList<>();

            for (String resultClass : resultClassNames) {
                SQLResultSetMapping mapping = new SQLResultSetMapping(resultClass);

                EntityResult entityResult = new EntityResult(resultClass);
                mapping.addResult(entityResult);

                resultSetMappings.add(mapping);
            }
            query = StoredProcedureQueryImpl.buildResultSetMappingQuery(resultSetMappings, call, hints, loader, (AbstractSession)session);
        } else if (resultSetMappingNames != null) {
            query = StoredProcedureQueryImpl.buildResultSetMappingNameQuery(resultSetMappingNames, call, hints, loader, (AbstractSession)session);
        } else if (resultClassName != null) {
            Class<?> clazz = session.getDatasourcePlatform().getConversionManager().convertClassNameToClass(resultClassName);
            query = StoredProcedureQueryImpl.buildStoredProcedureQuery(clazz, call, hints, loader, (AbstractSession)session);
        } else {
            // Neither a resultClass or resultSetMapping is specified so place in a temp query on the session.
            if (call.isStoredFunctionCall() || call.isStoredPLSQLProcedureCall()) {
                // If it is a function (plsql or not) or plsql procedure use the data read query.
                query = StoredProcedureQueryImpl.buildStoredProcedureQuery(call, hints, loader, (AbstractSession)session);
            } else {
                // Otherwise use a result set mapping query for stored procedure calls so users can use the execute
                // method on it (JPA 2.1 API). Will return the same result, that is, Object[] in this case.
                query = StoredProcedureQueryImpl.buildResultSetMappingQuery(new ArrayList<>(), call, hints, loader, (AbstractSession)session);
            }
        }
        query.setName(getName());

        return query;
    }

    public void setDatabaseQuery(DatabaseQuery databaseQuery) {
        setProperty("databasequery", databaseQuery);
    }

    /**
     * INTERNAL:
     * For table per tenant queries the descriptor list will extracted from
     * parsing the jpql query and cached here.
     */
    public void setDescriptors(List<ClassDescriptor> descriptors) {
        this.descriptors = descriptors;
    }

    public void setHints(Map<String, Object> hints){
        this.hints = hints;
    }

    @Override
    public void setJPQLString(String jpqlString){
        this.jpqlString = jpqlString;
    }

    public void setResultClassName(String className){
        this.resultClassName = className;
    }

    public void setResultSetMappings(List<String> resultSetMappings){
        this.resultSetMappingNames = resultSetMappings;
    }
}
