/*
 * 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 java.util.HashMap;
import java.util.List;

import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;

import junit.framework.TestSuite;

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.indirection.IndirectCollection;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.LoadGroup;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;

import org.junit.Test;

/**
 * Test named nested FetchGroup usage.
 *
 * @author dclarke
 * @since EclipseLink 2.1
 */
public class NestedDefaultFetchGroupTests extends BaseFetchGroupTests {

    public NestedDefaultFetchGroupTests() {
        super();
    }

    public NestedDefaultFetchGroupTests(String name) {
        super(name);
    }

    public static junit.framework.Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("NestedDefaultFetchGroupTests");

        suite.addTest(new NestedDefaultFetchGroupTests("testSetup"));
        suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployee"));
        suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddressAndPhoneUsingFetchGroup"));
        if (!isJPA10()) {
            suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddress"));
            suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadPhones"));
            suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddressAndPhones"));
            suite.addTest(new NestedDefaultFetchGroupTests("allAddress"));
            suite.addTest(new NestedDefaultFetchGroupTests("allPhone"));
            suite.addTest(new NestedDefaultFetchGroupTests("singleResultMinEmployeeFetchJoinAddress"));
            suite.addTest(new NestedDefaultFetchGroupTests("singleResultMinEmployeeFetchJoinAddressLoad"));
        }
        return suite;
    }

    /*
     * Set default fetch groups.
     *
     * @see EmployeeCustomizer
     * @see PhoneCustomizer
     */
    @Override
    public void setUp() {
        super.setUp();

        try {
            (new EmployeeCustomizer()).customize(employeeDescriptor);
            (new PhoneCustomizer()).customize(phoneDescriptor);
            // reprepare read queries after all fetch groups set into all descriptors.
            reprepareReadQueries(employeeDescriptor);
            reprepareReadQueries(phoneDescriptor);
        } catch (RuntimeException rtEx) {
            throw rtEx;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        assertConfig(employeeDescriptor, defaultEmployeeFG, 0);
        assertConfig(phoneDescriptor, defaultPhoneFG, 0);
    }

    @Test
    public void findMinEmployee() {
        internalFindMinEmployee(false, false, false);
    }

    @Test
    public void findMinEmployeeLoadAddress() {
        internalFindMinEmployee(true, false, true);
    }

    public void findMinEmployeeLoadPhones() {
        internalFindMinEmployee(false, true, true);
    }

    public void findMinEmployeeLoadAddressAndPhones() {
        internalFindMinEmployee(true, true, true);
    }

    public void findMinEmployeeLoadAddressAndPhoneUsingFetchGroup() {
        internalFindMinEmployee(true, true, false);
    }

    void internalFindMinEmployee(boolean loadAddress, boolean loadPhones, boolean useLoadGroup) {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        int minId = minEmployeeIdWithAddressAndPhones(em);
        assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        boolean load = false;
        boolean originalLoad = false;
        if(!useLoadGroup) {
            assertTrue(loadAddress == loadPhones);
            load = loadAddress;
            originalLoad = defaultEmployeeFG.shouldLoad();
            if(load != originalLoad) {
                defaultEmployeeFG.setShouldLoad(load);
            }
        }

        try {
            Employee emp;
            if(useLoadGroup) {
                LoadGroup lg = defaultEmployeeFG.toLoadGroup();
                if(!loadAddress) {
                    lg.removeAttribute("address");
                }
                if(!loadPhones) {
                    lg.removeAttribute("phoneNumbers");
                }
                HashMap<String, Object> hints = new HashMap(1);
                hints.put(QueryHints.LOAD_GROUP, lg);

                emp = em.find(Employee.class, minId, hints);
            } else {
                emp = em.find(Employee.class, minId);
            }

            assertNotNull(emp);
            int nExpected = 2;
            if(loadAddress) {
                nExpected++;
            }
            if(loadPhones) {
                nExpected++;
            }
            assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            boolean addressInstantiated = ((ValueHolderInterface) employeeDescriptor.getMappingForAttributeName("address").getAttributeValueFromObject(emp)).isInstantiated();
            assertTrue(loadAddress == addressInstantiated);

            boolean phonesInstantiated = ((IndirectCollection) employeeDescriptor.getMappingForAttributeName("phoneNumbers").getAttributeValueFromObject(emp)).isInstantiated();
            assertTrue(loadPhones == phonesInstantiated);

            emp.getAddress();
            emp.getPhoneNumbers().size();

            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(emp, defaultEmployeeFG);
            assertFetchedAttribute(emp, "address");
            assertFetchedAttribute(emp, "phoneNumbers");

            // Check Address
            FetchGroup fgAddress = defaultEmployeeFG.getGroup("address");
            assertFetched(emp.getAddress(), fgAddress);

            // Check phones
            FetchGroup fgPhones = defaultEmployeeFG.getGroup("phoneNumbers");
            for (PhoneNumber phone: emp.getPhoneNumbers()) {
                assertFetched(phone, fgPhones);
            }
        } finally {
            if(!useLoadGroup) {
                if(load != originalLoad) {
                    defaultEmployeeFG.setShouldLoad(originalLoad);
                }
            }
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }
/*    void internalFindMinEmployee(boolean loadAddress, boolean loadPhones) {
        EntityManager em = createEntityManager();
        int minId = minEmployeeIdWithAddressAndPhones(em);
        assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        FetchGroup fg = employeeDescriptor.getFetchGroupManager().getDefaultFetchGroup();
        FetchGroup phonesFg = fg.getGroup("phoneNumbers");

        FetchGroup fgAddress = fg.getGroup("address");
        boolean originalLoadAddress = fgAddress.shouldLoad();
        if(originalLoadAddress != loadAddress) {
            fgAddress.setShouldLoad(loadAddress);
        }

        FetchGroup fgPhones = fg.getGroup("phoneNumbers");
        boolean originalLoadPhones = fgPhones.shouldLoad();
        if(originalLoadPhones != loadPhones) {
            fgPhones.setShouldLoad(loadPhones);
        }

        try {
            Employee emp = em.find(Employee.class, minId);

            assertNotNull(emp);
            int nExpected = 2;
            if(loadAddress) {
                nExpected++;
            }
            if(loadPhones) {
                nExpected++;
            }
            assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

            boolean addressInstantiated = ((ValueHolderInterface)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("address")).getAttributeValueFromObject(emp)).isInstantiated();
            boolean phonesInstantiated = ((IndirectCollection)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("phoneNumbers")).getAttributeValueFromObject(emp)).isInstantiated();

            if(loadAddress) {
                assertTrue(addressInstantiated);
            }
            if(loadPhones) {
                assertTrue(phonesInstantiated);
            }

            emp.getAddress();
            emp.getPhoneNumbers().size();

            assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
            assertFetched(emp, defaultEmployeeFG);
            assertFetchedAttribute(emp, "address");
            assertFetchedAttribute(emp, "phoneNumbers");

            // Check Address
            assertFetched(emp.getAddress(), fgAddress);

            // Check phones
            for (PhoneNumber phone: emp.getPhoneNumbers()) {
                assertFetched(phone, fgPhones);
            }
        } finally {
            if(originalLoadAddress != loadAddress) {
                fgAddress.setShouldLoad(originalLoadAddress);
            }
            if(originalLoadPhones != loadPhones) {
                fgPhones.setShouldLoad(originalLoadPhones);
            }
        }
    }*/

    @Test
    public void allAddress() {
        EntityManager em = createEntityManager();


        List<Address> allAddresses = em.createQuery("SELECT a FROM Address a", Address.class).getResultList();

        for (Address address: allAddresses) {
            assertNoFetchGroup(address);
        }
    }

    @Test
    public void allPhone() {
        EntityManager em = createEntityManager();


        List<PhoneNumber> allPhones = em.createQuery("SELECT p FROM PhoneNumber p", PhoneNumber.class).getResultList();

        for (PhoneNumber phone: allPhones) {
            assertFetched(phone, defaultPhoneFG);
        }
    }

    @Test
    public void singleResultMinEmployeeFetchJoinAddress() {
        internalSingleResultMinEmployeeFetchJoinAddress(false);
    }
    public void singleResultMinEmployeeFetchJoinAddressLoad() {
        internalSingleResultMinEmployeeFetchJoinAddress(true);
    }
    void internalSingleResultMinEmployeeFetchJoinAddress(boolean shouldLoad) {
        EntityManager em = createEntityManager();

        TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.address WHERE e.id IN (SELECT MIN(p.id) FROM PhoneNumber p)", Employee.class);
        if(shouldLoad) {
            query.setHint(QueryHints.LOAD_GROUP_ATTRIBUTE, "phoneNumbers");
        }
        Employee emp = query.getSingleResult();

        assertNotNull(emp);
        int nExpected = 1;
        if(shouldLoad) {
            nExpected++;
        }
        assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
    }

    public static class EmployeeCustomizer implements DescriptorCustomizer {

        @Override
        public void customize(ClassDescriptor descriptor) throws Exception {
            defaultEmployeeFG = new FetchGroup("Employee.default");
            defaultEmployeeFG.addAttribute("firstName");
            defaultEmployeeFG.addAttribute("lastName");
            defaultEmployeeFG.addAttribute("address.country");
            defaultEmployeeFG.addAttribute("phoneNumbers.areaCode");

            descriptor.getFetchGroupManager().setDefaultFetchGroup(defaultEmployeeFG);
        }

    }

/*    public static class PhoneCustomizer implements DescriptorCustomizer {

        public void customize(ClassDescriptor descriptor) throws Exception {
            defaultPhoneFG = new FetchGroup<PhoneNumber>("PhoneNumber.default");
            defaultPhoneFG.addAttribute("number");
            descriptor.getFetchGroupManager().setDefaultFetchGroup(defaultPhoneFG);
        }

    }*/

}
