/*
 * Copyright (c) 2011, 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:
//     05/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup
package org.eclipse.persistence.testing.tests.jpa.fetchgroups;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Collection;
import java.util.Map;

import jakarta.persistence.EntityManagerFactory;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.indirection.IndirectContainer;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.Server;

/**
 * Test utility to verify the state of entities after they are loaded, copied,
 * or detached with respect to a defined FetchGroup.
 *
 * @author dclarke
 * @since EclipseLink 2.1.0
 */
public class FetchGroupAssert {

    /**
     * Verify that a FetchGroup is valid with respect to the mappings of the
     * provided entity class.
     */
    public static boolean isValid(FetchGroup fetchGroup, EntityManagerFactory emf, Class<?> entityClass) {
        assertNotNull(fetchGroup);
        Session session = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession();
        ClassDescriptor descriptor = session.getDescriptor(entityClass);
        try {
            for (Map.Entry<String, AttributeItem> entry : fetchGroup.getItems().entrySet()) {
                AttributeItem item = entry.getValue();
                DatabaseMapping mapping = descriptor.getMappingForAttributeName(item.getAttributeName());

                if (mapping.isForeignReferenceMapping()) {
                    if (item.getGroup() != null) {
                        if (!isValid((FetchGroup)item.getGroup(), emf, ((ForeignReferenceMapping) mapping).getReferenceClass())) {
                            return false;
                        }
                    }
                } else {
                    return false;
                }
            }
        } catch (QueryException qe) {
            return false;
        }
        return true;
    }

    /**
     * Verify that the attribute path specified is loaded in the provided entity
     */
    public static void assertFetchedAttribute(EntityManagerFactory emf, Object entity, String... attribute) {
        assertNotNull("EntityManagerFactory is null", emf);
        assertNotNull("Entity is null", entity);
        Server session = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession();
        assertNotNull("No Server session found for: " + emf, session);
        ClassDescriptor desc = session.getClassDescriptor(entity);
        assertNotNull("No descriptor found for: " + entity, desc);

        Object value = entity;
        if (attribute.length > 1) {
            String attrName = attribute[1];

            if (desc.hasFetchGroupManager()) {
                assertTrue("Attribute: '" + attrName + "' not fetched on: " + value, desc.getFetchGroupManager().isAttributeFetched(value, attrName));
            }
            DatabaseMapping mapping = desc.getMappingForAttributeName(attrName);
            value = mapping.getAttributeValueFromObject(value);

            if (value instanceof IndirectContainer) {
                value = ((IndirectContainer) value).getValueHolder();
            }
            if (value instanceof ValueHolderInterface) {
                ValueHolderInterface vhi = (ValueHolderInterface) value;
                assertTrue("ValueHolder for: '" + attrName + "' not instantiated", vhi.isInstantiated());
                value = vhi.getValue();
            }
            String[] tail = new String[attribute.length - 1];
            System.arraycopy(attribute, 1, tail, 0, attribute.length - 1);
            if (value instanceof Collection<?>) {
                for (Object obj : ((Collection<?>) value)) {
                    assertFetchedAttribute(emf, value, tail);
                }
            } else {
                assertFetchedAttribute(emf, value, tail);
            }
        } else {
            // This is where the actual end attribute in the path is validated.
            if (desc.hasFetchGroupManager()) {
                assertTrue(desc.getFetchGroupManager().isAttributeFetched(value, attribute[0]));
            }
        }
    }

    /**
     * Verify that the attribute path is loaded.
     */
    public static void assertNotFetchedAttribute(EntityManagerFactory emf, Object entity, String... attribute) {
        assertNotNull("EntityManagerFactory is null", emf);
        assertNotNull("Entity is null", entity);
        Server session = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession();
        assertNotNull("No Server session found for: " + emf, session);
        ClassDescriptor desc = session.getClassDescriptor(entity);
        assertNotNull("No descriptor found for: " + entity, desc);

        Object value = entity;
        for (int index = 0; index < attribute.length - 1; index++) {
            String attrName = attribute[index];

            if (desc.hasFetchGroupManager()) {
                assertTrue("Attribute: '" + attrName + "' not fetched on: " + value, desc.getFetchGroupManager().isAttributeFetched(value, attrName));
            }
            DatabaseMapping mapping = desc.getMappingForAttributeName(attrName);
            value = mapping.getAttributeValueFromObject(value);

            if (value instanceof IndirectContainer) {
                value = ((IndirectContainer) value).getValueHolder();
            }
            if (value instanceof ValueHolderInterface) {
                ValueHolderInterface vhi = (ValueHolderInterface) value;
                assertTrue("ValueHolder for: '" + attrName + "' not instantiated", vhi.isInstantiated());
                value = vhi.getValue();
            }
        }
    }

    /**
     * Assert that the entity provided has the attributes defined in the
     * FetchGroup loaded.
     *
     */
    public static void assertFetched(EntityManagerFactory emf, Object entity, FetchGroup fetchGroup) {
        assertNotNull("Null entity", entity);
        assertNotNull("No FetchGroup provided", fetchGroup);
        if (!(entity instanceof FetchGroupTracker)) {
            System.out.println();
        }
        assertTrue("Entity does not implement FetchGroupTracker: " + entity, entity instanceof FetchGroupTracker);

        FetchGroupTracker tracker = (FetchGroupTracker) entity;
        assertNotNull("FetchGroup on entity is null", tracker._persistence_getFetchGroup());
        FetchGroup groupToCompare = fetchGroup;
        if(!fetchGroup.isEntityFetchGroup()) {
            groupToCompare = new EntityFetchGroup(fetchGroup);
        }
        assertTrue("FetchGroup on entity does not equal provided", tracker._persistence_getFetchGroup().equals(groupToCompare));

        Server session = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession();
        assertNotNull(session);
        ClassDescriptor descriptor = session.getClassDescriptor(entity);
        assertNotNull(descriptor);
        assertTrue("", descriptor.getJavaClass().isAssignableFrom(entity.getClass()));

        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (descriptor.getObjectBuilder().getPrimaryKeyMappings().contains(mapping)) {
                assertTrue("PrimaryKey mapping not fetched: " + entity, tracker._persistence_isAttributeFetched(mapping.getAttributeName()));
            } else if (descriptor.usesOptimisticLocking() && descriptor.getOptimisticLockingPolicy() instanceof VersionLockingPolicy && ((VersionLockingPolicy) descriptor.getOptimisticLockingPolicy()).getVersionMapping() == mapping) {
                assertTrue("Optimistic version mapping not fetched: " + entity, tracker._persistence_isAttributeFetched(mapping.getAttributeName()));
            } else if (tracker._persistence_getFetchGroup().containsAttribute(mapping.getAttributeName())) {
                assertTrue(tracker._persistence_isAttributeFetched(mapping.getAttributeName()));
                // EntityFetchGroup never has nested fetch groups.
/*                AttributeItem attrFI = tracker._persistence_getFetchGroup().getItem(mapping.getAttributeName());
                if (attrFI.getGroup() != null) {
                    Object value = mapping.getAttributeValueFromObject(entity);
                    if (value instanceof IndirectContainer) {
                        assertTrue(((IndirectContainer) value).isInstantiated());
                        Collection<?> values = (Collection<?>) value;
                        for (Object val : values) {
                            assertFetched(emf, val, (FetchGroup)attrFI.getGroup());
                        }
                        return;
                    }
                    if (value instanceof ValueHolderInterface) {
                        assertTrue(((ValueHolderInterface) value).isInstantiated());
                        value = ((ValueHolderInterface) value).getValue();
                    }
                    if (value != null) {
                        assertFetched(emf, value, (FetchGroup)attrFI.getGroup());
                    }
                }*/
            } else { // Should not be fetched
                assertFalse(tracker._persistence_isAttributeFetched(mapping.getAttributeName()));
            }
        }
    }

    public static void assertDefaultFetched(EntityManagerFactory emf, Object entity) {
        assertNotNull("Null entity", entity);

        ClassDescriptor descriptor = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession().getClassDescriptor(entity);
        assertNotNull("No descriptor found for: " + entity, descriptor);

        assertTrue("No FetchGroupManager on: " + descriptor, descriptor.hasFetchGroupManager());

        FetchGroup defaultFG = descriptor.getFetchGroupManager().getDefaultFetchGroup();
        assertNotNull("No default FetchGroup on: " + descriptor, defaultFG);

        assertFetched(emf, entity, defaultFG);
    }

    public static void assertFetched(EntityManagerFactory emf, Object entity, String fetchGroupName) {
        assertNotNull("Null entity", entity);

        ClassDescriptor descriptor = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession().getClassDescriptor(entity);
        assertNotNull("No descriptor found for: " + entity, descriptor);

        assertTrue("No FetchGroupManager on: " + descriptor, descriptor.hasFetchGroupManager());

        FetchGroup fg = descriptor.getFetchGroupManager().getFetchGroup(fetchGroupName);

        assertNotNull("No FetchGroup named: " + fetchGroupName, fg);

        assertFetched(emf, entity, fg);
    }

    /**
     * Verify that the provided entity does not have a FetchGroup configured on
     * it.
     */
    public static void assertNoFetchGroup(EntityManagerFactory emf, Object entity) {
        if (entity instanceof FetchGroupTracker) {
            FetchGroupTracker tracker = (FetchGroupTracker) entity;

            assertNull("Entity: " + entity + " has: " + tracker._persistence_getFetchGroup(), tracker._persistence_getFetchGroup());
        }
    }

    public static void assertConfig(EntityManagerFactory emf, String entityName, FetchGroup defaultFetchGroup) {
        assertConfig(emf, entityName, defaultFetchGroup, 0);
    }

    public static void assertConfig(EntityManagerFactory emf, String entityName, FetchGroup defaultFetchGroup, int numNamedFetchGroups) {
        ClassDescriptor descriptor = ((org.eclipse.persistence.jpa.JpaEntityManager)emf.createEntityManager()).getServerSession().getClassDescriptorForAlias(entityName);
        assertNotNull("Not descriptor found for: " + entityName, descriptor);
        assertConfig(descriptor, defaultFetchGroup, numNamedFetchGroups);
    }

    public static void assertConfig(ClassDescriptor descriptor, FetchGroup defaultFetchGroup, int numNamedFetchGroups) {
        String entityName = descriptor.getAlias();

        assertTrue("FetchGroupTracker not implemented by: " + entityName, FetchGroupTracker.class.isAssignableFrom(descriptor.getJavaClass()));

        if (defaultFetchGroup == null) {
            assertNull("Default FetchGroup not null: " + entityName, descriptor.getFetchGroupManager().getDefaultFetchGroup());
        } else {
//            assertEquals("Default FetchGroup does not match", defaultFetchGroup, descriptor.getFetchGroupManager().getDefaultFetchGroup());
            if(defaultFetchGroup != descriptor.getFetchGroupManager().getDefaultFetchGroup()) {
                fail("Default FetchGroup does not match");
            }
        }

        if(numNamedFetchGroups != descriptor.getFetchGroupManager().getFetchGroups().size()) {
            fail("Incorrect number of Named FetchGroups: " + entityName);
        }
    }

    public static void assertConfig(ClassDescriptor descriptor, FetchGroup defaultFetchGroup) {
        assertConfig(descriptor, defaultFetchGroup, 0);
    }
}
