/*
 * 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


package org.eclipse.persistence.testing.tests.jpa.advanced;

import junit.framework.TestCase;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.EmployeeListener;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.Project;

import java.util.Vector;

import jakarta.persistence.EntityManager;

import junit.framework.TestSuite;
import junit.framework.Test;


/*
 * Suite used to contain Entity callback tests
 */
public class CallbackEventJUnitTestSuite extends JUnitTestCase {
    protected boolean m_reset = false;    // reset gets called twice on error

    protected int m_beforeEvent, m_afterEvent;


    public CallbackEventJUnitTestSuite() {
    }

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

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("CallbackEventJUnitTestSuite");

        suite.addTest(new CallbackEventJUnitTestSuite("testSetup"));
        suite.addTest(new CallbackEventJUnitTestSuite("testPersistThenRemoveCalls"));
        suite.addTest(new CallbackEventJUnitTestSuite("testRemoveUnmanagedNewEntity"));
        suite.addTest(new CallbackEventJUnitTestSuite("testPersistOnRegisteredObject"));
        suite.addTest(new CallbackEventJUnitTestSuite("testPreUpdateEvent_UpdateAltered"));
        suite.addTest(new CallbackEventJUnitTestSuite("testPreUpdateEvent_UpdateReverted"));
        suite.addTest(new CallbackEventJUnitTestSuite("testMergeCascadeTriggersPrePersist"));

        return suite;
    }

    /**
     * The setup is done as a test, both to record its failure, and to allow execution in the server.
     */
    public void testSetup() {
        new AdvancedTableCreator().replaceTables(JUnitTestCase.getServerSession());

        clearCache();
    }

    /*
     * test for bug 4568370:TopLink should perform an unregister on the remove call on a new object
     *   Calls persist/remove on an existing object which will cause a DB exception if the insert
     *   is generated.  It also checks that the prepersist/preremove callbacks get issued
     */
    public void testPersistThenRemoveCalls() throws Exception {
        clearCache();
        m_beforeEvent = EmployeeListener.PRE_REMOVE_COUNT;
        int m_beforePrePersistEvent = EmployeeListener.PRE_PERSIST_COUNT;

        EntityManager em = createEntityManager();
        beginTransaction(em);
        Employee employee = new Employee();
        try {
            employee = new Employee();
            em.persist(employee);
            em.remove(employee);
            commitTransaction(em);
        } catch (RuntimeException ex) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw ex;
        }
        m_afterEvent = EmployeeListener.PRE_REMOVE_COUNT;
        int m_afterPrePersistEvent = EmployeeListener.PRE_PERSIST_COUNT;
        if (em.find(Employee.class, employee.getId()) != null) {
            fail("Employee was inserted.");
        }
        closeEntityManager(em);
        assertTrue("The prePersist callback method was not called.", m_beforePrePersistEvent != m_afterPrePersistEvent);
        assertTrue("The preRemove callback method was not called.", m_beforeEvent != m_afterEvent);
    }


    public void testRemoveUnmanagedNewEntity() throws Exception {
        m_beforeEvent = EmployeeListener.PRE_REMOVE_COUNT;
        clearCache();
        EntityManager em = createEntityManager();
        beginTransaction(em);
        //new_emp should exist only in db
        try{
            Employee newEmp = new Employee();
            newEmp.setFirstName("new");
            newEmp.setLastName("guy2");
            em.remove(newEmp);
            commitTransaction(em);
        }catch (RuntimeException ex){
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw ex;
        }
        m_afterEvent = EmployeeListener.PRE_REMOVE_COUNT;
        closeEntityManager(em);

        assertTrue("The preRemove callback method was called, remove should have been ignored.", m_beforeEvent == m_afterEvent);
        //Employee emp = (Employee)em.find(Employee.class, new_emp.getId());

        //this.assertTrue("The remove should have been ignored.", m_beforeEvent == m_afterEvent);
    }

    public void testPersistOnRegisteredObject() {
        clearCache();
        EntityManager em = createEntityManager();
        beginTransaction(em);
        //create new employee and persist it
        try{
            Employee newEmp = new Employee();
            newEmp.setFirstName("new2");
            newEmp.setLastName("guy2");
            em.persist(newEmp);
            m_beforeEvent = EmployeeListener.POST_PERSIST_COUNT;
            em.persist(newEmp);
            m_afterEvent = EmployeeListener.POST_PERSIST_COUNT;
            rollbackTransaction(em);
        }catch (RuntimeException ex){
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw ex;
        }


        assertTrue("Calling persist on a managed object should be ignored", m_beforeEvent==m_afterEvent);
    }

    public void testPreUpdateEvent_UpdateAltered() {
        internalTestPreUpdateEvent(false);
    }

    public void testPreUpdateEvent_UpdateReverted() {
        internalTestPreUpdateEvent(true);
    }

    // PreUpdate event support must change to allow data modifications in event[PreUpdate]
    protected void internalTestPreUpdateEvent(boolean shouldUseOriginalName) {
        EntityManager em = createEntityManager();
        //moved from setUp so that it doesn't prevent the testSetup from running when the tables do not exist.
        Employee new_emp =null;
        beginTransaction(em);
        try{
            new_emp = new Employee();
            new_emp.setFirstName("New");
            new_emp.setLastName("Guy");
            em.persist(new_emp);
            commitTransaction(em);
        }catch (RuntimeException ex){
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            //rethrow since the test cannot run without the employee persisted
            throw ex;
        }
        clearCache();

        em = createEntityManager();

        Employee emp = null;
        int originalVersion = 0;
        String firstNameExpectedAfterCommit = "";
        beginTransaction(em);
        try{
            emp = em.find(Employee.class, new_emp.getId());
            originalVersion = getVersion(emp);
            if(shouldUseOriginalName) {
                firstNameExpectedAfterCommit = emp.getFirstName();
            } else {
                firstNameExpectedAfterCommit = "Updated" + emp.getFirstName();
            }
            // Assign a new first name to the employee:
            // it consists of a EmployeeListener.PRE_UPDATE_NAME_PREFIX
            // and either original first name or an updated one.
            String firstNameAssigned = EmployeeListener.PRE_UPDATE_NAME_PREFIX + firstNameExpectedAfterCommit;
            emp.setFirstName(firstNameAssigned);
            commitTransaction(em);
        }catch (RuntimeException ex){
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw ex;
        }

        // On commit, EmployeeListener will process PreUpdate event removing
        // EmployeeListener.PRE_UPDATE_NAME_PREFIX from firstName - therefore after commit
        // employee's first name should be firstNameExpectedAfterCommit.
        // In case shouldUseOriginalName==true, there should've been no update performed at all -
        // because by removing the prefix EmployeeListener reverts the object to its original state -
        // therefore in this case employee's versions before and after commit should be the same.
        // However change tracking will perform the update...

        // Verify the employee object from the cache first.
        emp = em.find(Employee.class, new_emp.getId());
        if(!emp.getFirstName().equals(firstNameExpectedAfterCommit)) {
            fail("In cache: wrong firstName = " + emp.getFirstName() + "; " + firstNameExpectedAfterCommit + " was expected");
        }
        int version = getVersion(emp);
        // Only check version if it was changed, because if it was reverted back change tracking will still detect change.
        if(!shouldUseOriginalName) {
            if(originalVersion >= version) {
                fail("In cache: wrong version = " + version + "; version > " + originalVersion + " was expected");
            }
        }

        // Verify the employee object from the db.
        emp = (Employee) em.createQuery("SELECT OBJECT(e) FROM Employee e WHERE e.id = "+new_emp.getId()).setHint("eclipselink.refresh", Boolean.TRUE).getSingleResult();
        if(!emp.getFirstName().equals(firstNameExpectedAfterCommit)) {
            fail("In DB: wrong firstName = " + emp.getFirstName() + "; " + firstNameExpectedAfterCommit + " was expected");
        }
        version = getVersion(emp);
        if(!shouldUseOriginalName) {
            if(originalVersion >= version) {
                fail("In DB: wrong version = " + version + "; version > " + originalVersion + " was expected");
            }
        }
    }

    // helper method, used by internalTestPreUpdate
    protected int getVersion(Employee emp) {
        Vector pk = new Vector();
        pk.add(emp.getId());
        return (Integer) getServerSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(emp, pk, getServerSession());
    }

    // gf 2894:  merge does not trigger prePersist callbacks
    public void testMergeCascadeTriggersPrePersist() {
        clearCache();
        EntityManager em = createEntityManager();

        try {
            beginTransaction(em);
            // create an employee and persist it
            Employee emp = new Employee();
            emp.setFirstName("James");
            emp.setLastName("Dean");
            em.persist(emp);

            // create a new project and associate to persistent employee
            Project newProj  = new Project();
            newProj.setName("Rebel Without a Cause");
            emp.addProject(newProj);
            newProj.addTeamMember(emp);
            // merge should trigger prePersist callback on project
            em.merge(emp);
            // merge returns a managed copy of an unmanaged instance
            Project managedProj = emp.getProjects().iterator().next();
            assertTrue("Cascading merge to a new object should trigger prePersist callback", managedProj.pre_persist_count == 1);
            em.merge(emp);
            // second merge should be ignored
            assertTrue("prePersist callback should only be triggered once", managedProj.pre_persist_count == 1);
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

}
