/*
 * 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.HashSet;
import java.util.Set;

import jakarta.persistence.EntityManager;

import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated;
import org.eclipse.persistence.testing.models.wdf.jpa1.node.Node;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestNode extends JPA1Base {

    @Test
    public void testRoot() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final int rootId = 1;
            Node root = new Node(rootId, null);
            em.persist(root);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            Node found = em.find(Node.class, rootId);
            verify(found != null, "no node found");
            verify(found.getParent() == null, "parent not null");
            verify(found.getChildren().size() == 0, "unexpected children");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testTwoGenerations() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final int rootId = 10;
            Node root = new Node(rootId, null);
            final int child1Id = 11;
            Node child1 = new Node(child1Id, root);
            Node child2 = new Node(12, root);
            em.persist(root);
            em.persist(child1);
            em.persist(child2);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            Node found = em.find(Node.class, rootId);
            verify(found != null, "no node found");
            verify(found.getParent() == null, "parent not null");
            verify(found.getChildren().size() == 2, "unexpected children");
            env.rollbackTransactionAndClear(em);
            env.beginTransaction(em);
            found = em.find(Node.class, child1Id);
            verify(found != null, "no node found");
            Node parent = found.getParent();
            verify(em.contains(parent), "parent not contained in em");
            verify(parent != null, "parent is null");
            verify(parent.getId() == rootId, "parent has not root id");
            verify(parent.getChildren().size() == 2, "unexpected children");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testChangeParent() {
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            // seed the data model
            env.beginTransaction(em);
            final int root1Id = 20;
            final int root2Id = 21;
            final int childId = 22;
            Node root1 = new Node(root1Id, null);
            Node root2 = new Node(root2Id, null);
            Node child = new Node(childId, root1);
            em.persist(root1);
            em.persist(root2);
            em.persist(child);
            env.commitTransactionAndClear(em);
            // change the parent
            env.beginTransaction(em);
            child = em.find(Node.class, childId);
            Node parent = child.getParent();
            root2 = em.find(Node.class, root2Id);
            Set<Node> children = parent.getChildren();
            parent.setChildren(null);
            child.setParent(root2);
            root2.setChildren(children);
            env.commitTransactionAndClear(em);
            verify(!parent.postUpdateWasCalled(), "root1 was updated but it is not the owning side of the relationship");
            verify(!root2.postUpdateWasCalled(), "root2 was updated but it is not the owning side of the relationship");
            verify(child.postUpdateWasCalled(), "child was not updated but it is the owning side of the relationship");
            // check the relationship
            env.beginTransaction(em);
            child = em.find(Node.class, childId);
            verify(child != null, "child is null");
            parent = child.getParent();
            verify(parent != null, "parent is null");
            root2 = em.find(Node.class, root2Id);
            verify(root2 == parent, "root2 != parent");
            verify(children != null, "children is null");
            children = root2.getChildren();
            verify(children.contains(child), "child not contained in set of children");
            root1 = em.find(Node.class, root1Id);
            Set children1 = root1.getChildren();
            verify(children1 == null || children1.isEmpty(), "children of root1 not null or empty");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCircle() {
        // in this tree, the root is defined by this.parent = this;
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            final int rootId = 30;
            Node root = new Node(rootId, null);
            root.setParent(root);
            Set<Node> children = new HashSet<Node>();
            children.add(root);
            root.setChildren(children);
            em.persist(root);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            Node found = em.find(Node.class, rootId);
            verify(found != null, "no node found");
            verify(found.getParent() == found, "parent != root");
            verify(found.getChildren().size() == 1, "unexpected children");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }
}
