/*
 * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. 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:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.tests.wdf.jpa1.relation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceException;

import org.junit.Assert;

import org.eclipse.persistence.testing.framework.wdf.Issue;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Course;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Hobby;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Material;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

public class TestList extends JPA1Base {
    private static final Integer EMP_ID_DORIS = 43;
    private static final Integer EMP_ID_SABINE = 44;

    @Override
    protected void setup()  {

        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Department dep = new Department(1, "Public Relations");
            em.persist(dep);
            final Employee emp1 = new Employee(EMP_ID_DORIS, "Doris", "Schr\u00f6der-K\u00f6pf", dep);
            em.persist(emp1);
            final Employee emp2 = new Employee(EMP_ID_SABINE, "Sabine", "Leutheusser-Schnarrenberger", dep);
            em.persist(emp2);
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCourse() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            env.commitTransactionAndClear(em);
            final Course storedCourse = em.find(Course.class, courseId);
            verify(storedCourse != null, "didn't find course again");
            verify(storedCourse.getAttendees() != null, "course lost attendees");
            verify(storedCourse.getAttendees().size() == 2, "number of attendees in course (expected: 2, got: "
                    + storedCourse.getAttendees().size() + ").");
            for (final Employee attendee : storedCourse.getAttendees()) {
                verify(attendee.getId() == EMP_ID_DORIS || attendee.getId() == EMP_ID_SABINE,
                        "Wrong attendee: " + attendee);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    private Course createAndPersistCourse(final EntityManager em) {
        final Course course = new Course();
        course.addAttendee(em.find(Employee.class, EMP_ID_DORIS));
        course.addAttendee(em.find(Employee.class, EMP_ID_SABINE));
        em.persist(course);
        // bug 312244
        Material material = new Material();
        course.setMaterial(material);
        material.setCourse(course);
        em.persist(material);
        // bug 312244
        return course;
    }

    @Test
    public void testDelete() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            em.remove(em.merge(course));
            env.commitTransactionAndClear(em);
            final Course storedCourse = em.find(Course.class, courseId);
            verify(storedCourse == null, "did find course again");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testMergeChangedRelation() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            // the remove of Doris takes place on the detached entity: but rather than relying on
            // cascade, the attendees are retrieved from em again.
            course.clearAttendees();
            course.addAttendee(em.find(Employee.class, EMP_ID_SABINE));
            final List<Employee> attendeesBeforeMerge = course.getAttendees();
            verify(attendeesBeforeMerge.size() == 1, "wrong number of attendees before merge(): " + attendeesBeforeMerge.size());
            final List<Employee> attendeesAfterMerge = em.merge(course).getAttendees();
            verify(attendeesAfterMerge.size() == 1, "wrong number of attendees after merge(): " + attendeesAfterMerge.size());
            env.commitTransactionAndClear(em);
            final Course storedCourse = em.find(Course.class, courseId);
            verify(storedCourse != null, "didnt find course again");
            verify(storedCourse.getAttendees() != null, "course lost attendees");
            verify(storedCourse.getAttendees().size() == 1, "number of attendees in course (expected: 1, got: "
                    + storedCourse.getAttendees().size() + ").");
            for (final Employee attendee : storedCourse.getAttendees()) {
                verify("Sabine".equals(attendee.getFirstName()), "Wrong attendee: " + attendee);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testUpdate() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            // the remove of Doris takes place on the managed entity
            em.find(Course.class, courseId).removeAttendee(em.find(Employee.class, EMP_ID_DORIS));
            env.commitTransactionAndClear(em);
            final Course storedCourse = em.find(Course.class, courseId);
            verify(storedCourse != null, "didnt find course again");
            verify(storedCourse.getAttendees() != null, "course lost attendees");
            verify(storedCourse.getAttendees().size() == 1, "number of attendees in course (expected: 1, got: "
                    + storedCourse.getAttendees().size() + ").");
            for (final Employee attendee : storedCourse.getAttendees()) {
                verify("Sabine".equals(attendee.getFirstName()), "Wrong attendee: " + attendee);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testOrderBy() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        final SortedMap<String, Employee> attendeeMap = new TreeMap<String, Employee>();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            final Employee employee1 = em.find(Employee.class, EMP_ID_DORIS);
            attendeeMap.put(employee1.getLastName(), employee1);
            final Employee employee2 = em.find(Employee.class, EMP_ID_SABINE);
            attendeeMap.put(employee2.getLastName(), employee2);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            final Course storedCourse = em.find(Course.class, courseId);
            verify(storedCourse != null, "didnt find course again");
            final List<Employee> attendees = storedCourse.getAttendees();
            verify(attendees != null, "course lost attendees");
            final Iterator<Employee> orderedEmployees = attendees.iterator();
            for (final String lastName : attendeeMap.keySet()) {
                Employee nextEmployee = orderedEmployees.next();
                verify(nextEmployee.getLastName().equals(lastName), "wrong order of employees, expected name: " + lastName
                        + ", but got name: " + nextEmployee.getLastName());
            }
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRelationContainsEntities() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final Course course = createAndPersistCourse(em);
            final Long courseId = course.getCourseId();
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            final Course storedCourse = em.find(Course.class, courseId);
            if (null == storedCourse || null == storedCourse.getAttendees()) {
                flop("didnt find course/attendees again");
            }
            for (final Employee attendee : storedCourse.getAttendees()) {
                verify(em.contains(attendee), "Attending Emloyee not known to entity manager: " + attendee);
            }
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Issue(issueid=12)
    public void testCompoundOrderBy() {
        final String[] increasingCategories = new String[] { null, " ", "Nonsense", "Sport", "Work", };
        final String[] decreasingDescriptions = new String[] { "Grumbling and Cursing", "Bla-muh", "A description", " ", null, };
        int id = increasingCategories.length * decreasingDescriptions.length;
        final List<Hobby> sortedHobbies = new ArrayList<Hobby>();
        for (final String category : increasingCategories) {
            for (final String description : decreasingDescriptions) {
                id--;
                final Hobby hobby = new Hobby(description);
                hobby.setCategory(category);
                sortedHobbies.add(hobby);
            }
        }
        final List<Hobby> dorisSortedHobbies = new ArrayList<Hobby>(sortedHobbies);
        dorisSortedHobbies.remove(24);
        dorisSortedHobbies.remove(23);
        dorisSortedHobbies.remove(19);
        dorisSortedHobbies.remove(13);
        dorisSortedHobbies.remove(9);
        dorisSortedHobbies.remove(4);
        dorisSortedHobbies.remove(3);
        dorisSortedHobbies.remove(2);
        final List<Hobby> dorisShuffledHobbies = new ArrayList<Hobby>(dorisSortedHobbies);
        Collections.shuffle(dorisShuffledHobbies);
        final List<Hobby> sabineSortedHobbies = new ArrayList<Hobby>(sortedHobbies);
        sabineSortedHobbies.removeAll(dorisShuffledHobbies);
        final List<Hobby> sabineShuffledHobbies = new ArrayList<Hobby>(sabineSortedHobbies);
        Collections.shuffle(sabineShuffledHobbies);
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            for (final Hobby hobby : sortedHobbies) {
                em.persist(hobby);
            }
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            final Employee doris = em.find(Employee.class, EMP_ID_DORIS);
            doris.setHobbies(dorisShuffledHobbies);
            final Employee sabine = em.find(Employee.class, EMP_ID_SABINE);
            sabine.setHobbies(sabineShuffledHobbies);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            final Employee persistentDoris = em.find(Employee.class, EMP_ID_DORIS);
            final List<Hobby> persistentDorisHobbies = persistentDoris.getHobbies();
            verify(persistentDorisHobbies.equals(dorisSortedHobbies), "Doris' hobbies are not sorted correctly, got >>"
                    + persistentDorisHobbies + "<<, expected >>" + dorisSortedHobbies + "<<.");
            final Employee persistentSabine = em.find(Employee.class, EMP_ID_SABINE);
            final List<Hobby> persistentSabineHobbies = persistentSabine.getHobbies();
            env.commitTransaction(em);
            // no clear here, wana access persistentSabineHobbies outside the transaction.
            final boolean expectException = false; // env instanceof JTASharedPCEnvironment;
            try {
                verify(persistentSabineHobbies.equals(sabineSortedHobbies), "Sabine's hobbies are not sorted correctly, got >>"
                        + persistentSabineHobbies + "<<, expected >>" + sabineSortedHobbies + "<<.");
                if (expectException) {
                    flop("No exception when accessing a lazy list outside.");
                }
            } catch (PersistenceException ex) {
                if (expectException) {
                    Assert.assertTrue(true);
                } else {
                    throw ex;
                }
            }
            em.clear();
        } finally {
            closeEntityManager(em);
        }
    }
}
