/*
 * Copyright (c) 2012, 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.tests.jpql.tools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import jakarta.persistence.AccessType;
import jpql.query.Address;
import jpql.query.Employee;
import jpql.query.EnumType;
import jpql.query.Project;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPAVersion;
import org.eclipse.persistence.jpa.jpql.parser.JPQLGrammar;
import org.eclipse.persistence.jpa.jpql.tools.AbstractJPQLQueryHelper;
import org.eclipse.persistence.jpa.jpql.tools.ContentAssistExtension;
import org.eclipse.persistence.jpa.jpql.tools.ContentAssistProposals;
import org.eclipse.persistence.jpa.jpql.tools.ContentAssistProposals.EnumProposals;
import org.eclipse.persistence.jpa.jpql.tools.spi.IEntity;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.utility.CollectionTools;
import org.eclipse.persistence.jpa.tests.jpql.JPQLCoreTest;
import org.eclipse.persistence.jpa.tests.jpql.JPQLQueryHelperTestHelper;
import org.eclipse.persistence.jpa.tests.jpql.parser.JPQLQueryBNFAccessor;
import org.eclipse.persistence.jpa.tests.jpql.tools.spi.java.JavaQuery;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;
import static org.junit.Assert.*;

/**
 * The abstract unit-test providing helper methods required for testing content assist.
 *
 * @version 2.5
 * @since 2.5
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public abstract class ContentAssistTest extends JPQLCoreTest {

    protected JPQLQueryBNFAccessor bnfAccessor;
    @JPQLQueryHelperTestHelper
    protected AbstractJPQLQueryHelper queryHelper;
    protected JavaQuery virtualQuery;

    /**
     * Returns the return type associated with the given JPQL identifier. Only JPQL identifiers mark
     * with {@link org.eclipse.persistence.jpa.jpql.parser.IdentifierRole#FUNCTION} have a return
     * type.
     *
     * @param identifier The JPQL identifier for which its expected return type should be returned
     * @return Either the return type for the given JPQL identifier or <code>null</code> if the
     * expression does not return a value
     */
    protected Class<?> acceptableType(String identifier) {
        return null;
    }

    /**
     * Creates a new {@link ContentAssistExtension} that can be used to provide additional
     * information that is outside the scope of simply providing JPA metadata information,
     * such as table names, column names, class names.
     *
     * @return By default, {@link ContentAssistExtension#NULL_HELPER} is returned
     */
    protected ContentAssistExtension buildContentAssistExtension() {
        return ContentAssistExtension.NULL_HELPER;
    }

    /**
     * Retrieves the possibles choices that can complete the query from the given position of the
     * cursor within the JPQL query.
     *
     * @param jpqlQuery The JPQL query to parse and for which content assist proposals will be
     * calculated based on the position of the cursor within that query
     * @param position The position of the cursor within the given JPQL query
     * @return The list of valid proposals regrouped by categories
     */
    protected final ContentAssistProposals buildContentAssistProposals(String jpqlQuery, int position) {
        virtualQuery.setExpression(jpqlQuery);
        queryHelper.setQuery(virtualQuery);
        return queryHelper.buildContentAssistProposals(position, buildContentAssistExtension());
    }

    /**
     * Creates an array of two elements containing the result of calculating the valid proposals.
     *
     * @param jpqlQuery The JPQL query to parse and for which content assist proposals will be
     * calculated based on the position of the cursor within that query
     * @param position The position of the cursor within the given JPQL query
     * @param proposals The collection of expected proposals
     * @return The result based on what was found and what is expected:
     * <ul>
     * <li>Index 0: Proposals that were not found by content assist but that are expected;</li>
     * <li>Index 1: Proposals that were found by content assist but that are not expected.</li>
     * </ul>
     */
    @SuppressWarnings("unchecked")
    protected List<String>[] buildResults(String jpqlQuery,
                                          int position,
                                          Iterable<String> proposals) {

        // In case the Iterable is read-only
        List<String> expectedProposals = new ArrayList<>();
        CollectionTools.addAll(expectedProposals, proposals);

        ContentAssistProposals contentAssistProposals = buildContentAssistProposals(jpqlQuery, position);
        List<String> unexpectedProposals = new ArrayList<>();

        // Entities
        for (IEntity entity : contentAssistProposals.abstractSchemaTypes()) {
            handleProposal(expectedProposals, unexpectedProposals, entity.getName());
        }

        // Class names
        for (String className : contentAssistProposals.classNames()) {
            handleProposal(expectedProposals, unexpectedProposals, className);
        }

        // Column names
        for (String columnName : contentAssistProposals.columnNames()) {
            handleProposal(expectedProposals, unexpectedProposals, columnName);
        }

        // Enum constant names
        for (EnumProposals enumProposals : contentAssistProposals.enumConstant()) {
            // Iterate through the list of enum constants
            for (String enumConstantName : enumProposals.enumConstants()) {
                handleProposal(expectedProposals, unexpectedProposals, enumConstantName);
            }
        }

        // Identification variables
        for (String identificationVariable : contentAssistProposals.identificationVariables()) {
            handleProposal(expectedProposals, unexpectedProposals, identificationVariable);
        }

        // JPQL identifiers
        for (String identifier : contentAssistProposals.identifiers()) {
            handleProposal(expectedProposals, unexpectedProposals, identifier);
        }

        // Mappings
        for (IMapping mapping : contentAssistProposals.mappings()) {
            handleProposal(expectedProposals, unexpectedProposals, mapping.getName());
        }

        // Table names
        for (String tableName : contentAssistProposals.tableNames()) {
            handleProposal(expectedProposals, unexpectedProposals, tableName);
        }

        // The remaining proposals were not part of any proposal list
        List<String> proposalsNotRemoved = new ArrayList<>();
        CollectionTools.addAll(proposalsNotRemoved, expectedProposals);

        return (List<String>[]) new List[] { proposalsNotRemoved, unexpectedProposals };
    }

    protected List<String> classNames() {
        List<String> classNames = new ArrayList<>();
        classNames.add(Address      .class.getName());
        classNames.add(ArrayList    .class.getName());
        classNames.add(Employee     .class.getName());
        classNames.add(Project      .class.getName());
        classNames.add(String       .class.getName());
        classNames.add(StringBuilder.class.getName());
        return classNames;
    }

    protected final Iterable<String> collectionValuedFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.COLLECTION_VALUED_FIELD);
    }

    protected List<String> columnNames(String tableName) {

        List<String> columnNames = new ArrayList<>();

        if ("EMPLOYEE".equals(tableName)) {
            columnNames.add("ADDRESS");
            columnNames.add("EMPLOYEE_ID");
            columnNames.add("FIRST_NAME");
            columnNames.add("LAST_NAME");
            columnNames.add("MANAGER");
        }
        else if ("ADDRESS".equals(tableName)) {
            columnNames.add("ADDRESS_ID");
            columnNames.add("APT_NUMBER");
            columnNames.add("COUNTRY");
            columnNames.add("STREET");
            columnNames.add("ZIP_CODE");
        }

        return columnNames;
    }

    protected Class<?> defaultAcceptableType(String identifier) {

        if (identifier == ABS   ||
            identifier == PLUS  ||
            identifier == MINUS ||
            identifier == AVG   ||
            identifier == MOD   ||
            identifier == SQRT  ||
            identifier == SUM) {

            return Number.class;
        }

        if (identifier == CONCAT    ||
            identifier == LENGTH    ||
            identifier == LOCATE    ||
            identifier == LOWER     ||
            identifier == SUBSTRING ||
            identifier == TRIM      ||
            identifier == UPPER) {

            return String.class;
        }

        return null;
    }

    protected final Iterable<IEntity> entities() throws Exception {
        return getPersistenceUnit().entities();
    }

    protected final Iterable<String> entityNames() throws Exception {
        List<String> names = new ArrayList<>();
        for (IEntity entity : entities()) {
            names.add(entity.getName());
        }
        return names;
    }

    protected List<String> enumConstants() {

        List<String> names = new ArrayList<>();

        for (Enum<EnumType> enumType : EnumType.values()) {
            names.add(enumType.name());
        }

        return names;
    }

    protected List<String> enumTypes() {
        List<String> classNames = new ArrayList<>();
        classNames.add(EnumType  .class.getName());
        classNames.add(AccessType.class.getName());
        return classNames;
    }

    protected final Iterable<String> filter(Iterable<String> proposals, String startsWith) {

        List<String> results = new ArrayList<>();

        for (String proposal : proposals) {
            if (ExpressionTools.startWithIgnoreCase(proposal, startsWith)) {
                results.add(proposal);
            }
        }

        return results;
    }

    protected final Iterable<String> filter(String[] proposals, String startsWith) {
        return filter(Arrays.asList(proposals), startsWith);
    }

    protected final JPQLGrammar getGrammar() {
        return queryHelper.getGrammar();
    }

    protected final JPQLQueryBNFAccessor getQueryBNFAccessor() {
        return bnfAccessor;
    }

    protected final AbstractJPQLQueryHelper getQueryHelper() {
        return queryHelper;
    }

    protected final JavaQuery getVirtualQuery() {
        return virtualQuery;
    }

    private void handleProposal(Iterable<String> expectedProposals,
                                List<String> unexpectedProposals,
                                String possibleProposal) {

        boolean removed = false;

        // Iterate through the expected proposals and see if the class name is expected
        for (Iterator<String> iter = expectedProposals.iterator(); iter.hasNext(); ) {

            String expectedProposal = iter.next();

            // The proposal is an expected proposal
            if (expectedProposal.equalsIgnoreCase(possibleProposal)) {
                // Remove it from the list of expected proposals
                iter.remove();
                // Indicate it was removed, if not, we'll add the proposal
                // to the list of unexpected proposals
                removed = true;
                break;
            }
        }

        // The proposal found by content assist is not expected
        if (!removed) {
            unexpectedProposals.add(possibleProposal);
        }
    }

    protected final boolean isJPA1_0() {
        return jpqlGrammar().getJPAVersion() == JPAVersion.VERSION_1_0;
    }

    protected final boolean isJPA2_0() {
        return jpqlGrammar().getJPAVersion() == JPAVersion.VERSION_2_0;
    }

    protected final boolean isJPA2_1() {
        return jpqlGrammar().getJPAVersion() == JPAVersion.VERSION_2_1;
    }

    protected final List<String> joinIdentifiers() {
        List<String> proposals = new ArrayList<>();
        proposals.add(INNER_JOIN);
        proposals.add(INNER_JOIN_FETCH);
        proposals.add(JOIN);
        proposals.add(JOIN_FETCH);
        proposals.add(LEFT_JOIN);
        proposals.add(LEFT_JOIN_FETCH);
        proposals.add(LEFT_OUTER_JOIN);
        proposals.add(LEFT_OUTER_JOIN_FETCH);
        return proposals;
    }

    protected final List<String> joinOnlyIdentifiers() {
        List<String> proposals = new ArrayList<>();
        proposals.add(INNER_JOIN);
        proposals.add(JOIN);
        proposals.add(LEFT_JOIN);
        proposals.add(LEFT_OUTER_JOIN);
        return proposals;
    }

    protected final JPQLGrammar jpqlGrammar() {
        return queryHelper.getGrammar();
    }

    protected final Iterable<String> nonTransientFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.NON_TRANSIENT);
    }

    protected final Iterable<String> relationshipAndCollectionFieldNames(Class<?> persistentType) throws Exception {
        Set<String> uniqueNames = new HashSet<>();
        CollectionTools.addAll(uniqueNames, relationshipFieldNames(persistentType));
        CollectionTools.addAll(uniqueNames, collectionValuedFieldNames(persistentType));
        return uniqueNames;
    }

    protected final Iterable<String> relationshipFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.RELATIONSHIP_FIELD);
    }

    protected final <T extends Collection<String>> T removeAll(T items1, Iterable<String> items2) {
        for (String item2 : items2) {
            items1.remove(item2);
        }
        return items1;
    }

    protected final Iterable<String> retrieveMappingNames(Class<?> persistentType,
                                                          MappingType mappingType) throws Exception {

        return retrieveMappingNames(persistentType, mappingType, null);
    }

    protected final Iterable<String> retrieveMappingNames(Class<?> persistentType,
                                                          MappingType mappingType,
                                                          Class<?> allowedType) throws Exception {

        IManagedType managedType = getPersistenceUnit().getManagedType(persistentType.getName());

        if (managedType == null) {
            return Collections.emptyList();
        }

        List<String> names = new ArrayList<>();
        IType type = (allowedType != null) ? getPersistenceUnit().getTypeRepository().getType(allowedType) : null;

        for (IMapping mapping : managedType.mappings()) {

            if (mappingType.isValid(mapping) &&
                ((type == null) || mapping.getType().isAssignableTo(type))) {

                names.add(mapping.getName());
            }
            // Allow incomplete path
            else if (mappingType == MappingType.SINGLE_VALUED_OBJECT_FIELD) {
                if (mapping.isRelationship() && !mapping.isCollection()) {
                    names.add(mapping.getName());
                }
            }
        }

        return names;
    }

    @Override
    protected void setUpClass() throws Exception {
        super.setUpClass();
        virtualQuery = new JavaQuery(getPersistenceUnit(), null);
        bnfAccessor  = new JPQLQueryBNFAccessor(getGrammar().getExpressionRegistry());
    }

    protected final Iterable<String> singledValuedObjectFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.SINGLE_VALUED_OBJECT_FIELD);
    }

    protected final Iterable<String> singledValuedObjectFieldNames(Class<?> persistentType,
                                                                   Class<?> allowedType) throws Exception {

        return retrieveMappingNames(persistentType, MappingType.SINGLE_VALUED_OBJECT_FIELD, allowedType);
    }

    protected final Iterable<String> stateFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.STATE_FIELD);
    }

    protected final Iterable<String> stateFieldNames(Class<?> persistentType, Class<?> allowedType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.STATE_FIELD, allowedType);
    }

    protected List<String> tableNames() {

        List<String> tableNames = new ArrayList<>();
        tableNames.add("ADDRESS");
        tableNames.add("EMPLOYEE");
        tableNames.add("EMPLOYEE_SEQ");
        tableNames.add("MANAGER");
        tableNames.add("DEPARTMENT");

        return tableNames;
    }

    @Override
    protected void tearDown() throws Exception {
        queryHelper.dispose();
        virtualQuery.setExpression(null);
        super.tearDown();
    }

    @Override
    protected void tearDownClass() throws Exception {
        bnfAccessor  = null;
        queryHelper  = null;
        virtualQuery = null;
        super.tearDownClass();
    }

    protected final void testDoesNotHaveTheseProposals(String jpqlQuery,
                                                       int position,
                                                       Enum<?>... proposals) {

        testDoesNotHaveTheseProposals(jpqlQuery, position, toString(proposals));
    }

    protected final void testDoesNotHaveTheseProposals(String jpqlQuery,
                                                       int position,
                                                       Iterable<String> proposals) {

        List<String>[] results = buildResults(jpqlQuery, position, Collections.<String>emptyList());
        List<String> expectedEroposals = results[1];
        List<String> unexpectedProposals = new ArrayList<>();

        for (String proposal : proposals) {
            if (expectedEroposals.remove(proposal)) {
                unexpectedProposals.add(proposal);
            }
        }

        assertTrue(unexpectedProposals + " should not be proposals.", unexpectedProposals.isEmpty());
    }

    protected final void testDoesNotHaveTheseProposals(String jpqlQuery,
                                                       int position,
                                                       String... proposals) {

        testDoesNotHaveTheseProposals(jpqlQuery, position, CollectionTools.list(proposals));
    }

    protected final void testHasNoProposals(String jpqlQuery, int position) {
        List<String>[] results = buildResults(jpqlQuery, position, Collections.<String>emptyList());
        List<String> unexpectedProposals = results[1];
        assertTrue(unexpectedProposals + " should not be proposals.", unexpectedProposals.isEmpty());
    }

    protected final void testHasOnlyTheseProposals(String jpqlQuery,
                                                   int position,
                                                   Enum<?>... proposals) {

        testHasOnlyTheseProposals(jpqlQuery, position, toString(proposals));
    }

    protected final void testHasOnlyTheseProposals(String jpqlQuery, int position, Iterable<String> proposals) {

        List<String>[] results = buildResults(jpqlQuery, position, proposals);
        List<String> proposalsNotRemoved = results[0];
        List<String> unexpectedProposals = results[1];

        // Inconsistent list of proposals
        if (!unexpectedProposals.isEmpty() && !proposalsNotRemoved.isEmpty()) {
            if (proposalsNotRemoved.size() == 1) {
                fail(proposalsNotRemoved.get(0) + " should be a proposal and " + unexpectedProposals + " should not be a proposal.");
            }
            else {
                fail(proposalsNotRemoved + " should be proposals and " + unexpectedProposals + " should not be proposals.");
            }
        }
        // Added more proposals than it should
        else if (!unexpectedProposals.isEmpty() && proposalsNotRemoved.isEmpty()) {
            if (proposalsNotRemoved.size() == 1) {
                fail(unexpectedProposals.get(0) + " should not be a proposal.");
            }
            else {
                fail(unexpectedProposals + " should not be proposals.");
            }
        }
        // Forgot to add some proposals
        else if (!proposalsNotRemoved.isEmpty()) {
            if (proposalsNotRemoved.size() == 1) {
                fail(proposalsNotRemoved.get(0) + " should be a proposal.");
            }
            else {
                fail(proposalsNotRemoved + " should be proposals.");
            }
        }
    }

    protected final void testHasOnlyTheseProposals(String jpqlQuery,
                                                   int position,
                                                   String... proposals) {

        if (proposals.length == 0) {
            fail("The list of expected proposals cannot be empty");
        }

        testHasOnlyTheseProposals(jpqlQuery, position, CollectionTools.list(proposals));
    }

    protected final void testHasTheseProposals(String jpqlQuery,
                                               int position,
                                               Enum<?>... enums) {

        testHasTheseProposals(jpqlQuery, position, toString(enums));
    }

    protected final void testHasTheseProposals(String jpqlQuery,
                                               int position,
                                               Iterable<String> proposals) {

        List<String>[] results = buildResults(jpqlQuery, position, proposals);
        List<String> proposalsNotRemoved = results[0];
        assertTrue(proposalsNotRemoved + " should be proposals.", proposalsNotRemoved.isEmpty());
    }

    protected final void testHasTheseProposals(String jpqlQuery,
                                               int position,
                                               String... proposals) {

        testHasTheseProposals(jpqlQuery, position, CollectionTools.list(proposals));
    }

    protected final String[] toString(Enum<?>[] enums) {

        String[] names = new String[enums.length];

        for (int index = enums.length; --index >= 0; ) {
            names[index] = enums[index].name();
        }

        return names;
    }

    protected final Iterable<String> transientFieldNames(Class<?> persistentType) throws Exception {
        return retrieveMappingNames(persistentType, MappingType.TRANSIENT);
    }

    private enum MappingType {

        COLLECTION_VALUED_FIELD {
            @Override
            public boolean isValid(IMapping mapping) {
                return mapping.isCollection();
            }
        },

        NON_TRANSIENT {
            @Override
            public boolean isValid(IMapping mapping) {
                return !mapping.isTransient();
            }
        },

        RELATIONSHIP_FIELD {
            @Override
            public boolean isValid(IMapping mapping) {
                return mapping.isRelationship() && !mapping.isCollection();
            }
        },

        SINGLE_VALUED_OBJECT_FIELD {
            @Override
            public boolean isValid(IMapping mapping) {
                return !mapping.isTransient() && !mapping.isCollection();
            }
        },

        STATE_FIELD {
            @Override
            public boolean isValid(IMapping mapping) {
                return mapping.isProperty();
            }
        },

        TRANSIENT {
            @Override
            public boolean isValid(IMapping mapping) {
                return mapping.isTransient();
            }
        };

        abstract boolean isValid(IMapping mapping);
    }
}
