/*
 * 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.framework.wdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.LockModeType;
import jakarta.persistence.Persistence;
import javax.sql.DataSource;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
import org.eclipse.persistence.testing.framework.server.JEEPlatform;
import org.eclipse.persistence.testing.framework.server.ServerPlatform;
import org.eclipse.persistence.testing.tests.feature.TestDataSource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameters;

@SuppressWarnings("unchecked")
@RunWith(SkipBugzillaTestRunner.class)
public abstract class AbstractBaseTest {

    // /** System variable to set the tests to run on the server. */
    // public static final String RUN_ON_SERVER = "server.run";
    //
    private static Map<String, EntityManagerFactory> emfNamedPersistenceUnits = new Hashtable<String, EntityManagerFactory>();

    /** Determine if the test is running on a JEE server, or in JSE. */

    private static ServerPlatform serverPlatform;

    private final JPAEnvironment environment;
    private final String puName;
    private final static DataSource dataSource;
    protected final static Map EMF_PROPERTIES;

    private static boolean seesJPA2 = (LockModeType.values().length > 2);

    static {
        final DataSource aDataSource;

        if (!ServerInfoHolder.isOnServer()) {
            Map<String, String> properties = JUnitTestCaseHelper.getDatabaseProperties();
            String driver = properties.get(PersistenceUnitProperties.JDBC_DRIVER);
            String url = properties.get(PersistenceUnitProperties.JDBC_URL);
            String user = properties.get(PersistenceUnitProperties.JDBC_USER);
            String password = properties.get(PersistenceUnitProperties.JDBC_PASSWORD);

            Properties userPasswd = new Properties();
            userPasswd.put("user", user);
            userPasswd.put("password", password);

            DataSource ds = new TestDataSource(driver, url, userPasswd);
            aDataSource = new PooledDataSource(ds);

        } else {
            Context context;
            try {
                context = new InitialContext();
                aDataSource = (DataSource) context.lookup(ServerInfoHolder.getDataSourceName());
            } catch (NamingException e) {
                throw new RuntimeException(e);
            }
        }
        dataSource = aDataSource;
        EMF_PROPERTIES = new HashMap();
        EMF_PROPERTIES.put("delimited-identifiers", "true");
        EMF_PROPERTIES.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, dataSource);
    }

    public AbstractBaseTest(String name) {
        environment = new ResourceLocalEnvironment();
        puName = name;
    }

    protected final JPAEnvironment getEnvironment() {
        return environment;
    }

    @Parameters
    public static void parameters() {

    }

    final class ResourceLocalEnvironment implements JPAEnvironment {

        @Override
        public void beginTransaction(EntityManager em) {
            em.getTransaction().begin();
        }

        @Override
        public void commitTransaction(EntityManager em) {
            em.getTransaction().commit();
        }

        @Override
        public void commitTransactionAndClear(EntityManager em) {
            try {
                commitTransaction(em);
            } finally {
                em.clear();
            }
        }

        @Override
        public EntityManagerFactory createNewEntityManagerFactory() throws NamingException {
            AbstractBaseTest.closeEntityManagerFactory(puName);
            return Persistence.createEntityManagerFactory(puName, EMF_PROPERTIES);
        }

        @Override
        public EntityManager getEntityManager() {
            return getEntityManagerFactory().createEntityManager();
            // return AbstractBaseTest.createEntityManager(puName,
            // EMF_PROPERTIES);
        }

        @Override
        public EntityManagerFactory getEntityManagerFactory() {
            return AbstractBaseTest.getEntityManagerFactory(puName, EMF_PROPERTIES);
        }

        @Override
        public boolean isTransactionActive(EntityManager em) {
            return em.getTransaction().isActive();
        }

        @Override
        public boolean isTransactionMarkedForRollback(EntityManager em) {
            return em.getTransaction().getRollbackOnly();
        }

        @Override
        public void markTransactionForRollback(EntityManager em) {
            em.getTransaction().setRollbackOnly();
        }

        @Override
        public void rollbackTransaction(EntityManager em) {
            em.getTransaction().rollback();
        }

        @Override
        public void rollbackTransactionAndClear(EntityManager em) {
            try {
                rollbackTransaction(em);
            } finally {
                em.clear();
            }
        }

        @Override
        public boolean usesExtendedPC() {
            return true;
        }

        @Override
        public DataSource getDataSource() {
            return AbstractBaseTest.this.getDataSource();
        }

        @Override
        public EntityManagerFactory createNewEntityManagerFactory(Map properties) throws NamingException {
            Map mergedProperties = new HashMap();
            mergedProperties.putAll(EMF_PROPERTIES);
            mergedProperties.putAll(properties);

            AbstractBaseTest.closeEntityManagerFactory(puName);
            return Persistence.createEntityManagerFactory(puName, mergedProperties);
        }

        @Override
        public Object getPropertyValue(EntityManager em, String key) {
            Object delegate = em.getDelegate();
            Method getEntityManagerFactoryMethod;
            try {
                getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory");
                Object emf = getEntityManagerFactoryMethod.invoke(delegate);

                Method getPropertiesMethod = emf.getClass().getMethod("getProperties");
                @SuppressWarnings("rawtypes")
                Map map = (Map) getPropertiesMethod.invoke(emf);

                return map.get(key);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }

        }

        @Override
        public void evict(EntityManager em, Class<?> clazz) {
            Object delegate = em.getDelegate();
            Method getEntityManagerFactoryMethod;
            try {
                getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory");
                Object emf = getEntityManagerFactoryMethod.invoke(delegate);

                Method getCacheMethod = emf.getClass().getMethod("getCache");
                Object cache =  getCacheMethod.invoke(emf);

                Method evictClassMethod = cache.getClass().getMethod("evict", Class.class);

                evictClassMethod.invoke(cache, clazz);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void evictAll(EntityManager em) {
            Object delegate = em.getDelegate();
            Method getEntityManagerFactoryMethod;
            try {
                getEntityManagerFactoryMethod = delegate.getClass().getMethod("getEntityManagerFactory");
                Object emf = getEntityManagerFactoryMethod.invoke(delegate);

                Method getCacheMethod = emf.getClass().getMethod("getCache");
                Object cache =  getCacheMethod.invoke(emf);

                Method evictClassMethod = cache.getClass().getMethod("evictAll", new Class[]{});

                evictClassMethod.invoke(cache, new Object[]{});
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

    }

    final class JTATxScopedEnvironment implements JPAEnvironment {

        @Override
        public void beginTransaction(EntityManager em) {
            AbstractBaseTest.this.beginTransaction(em);
        }

        @Override
        public void commitTransaction(EntityManager em) {
            AbstractBaseTest.this.commitTransaction(em);
        }

        @Override
        public void commitTransactionAndClear(EntityManager em) {
            try {
                commitTransaction(em);
            } finally {
                em.clear();
            }
        }

        @Override
        public EntityManagerFactory createNewEntityManagerFactory() throws NamingException {
            AbstractBaseTest.closeEntityManagerFactory(puName);
            return Persistence.createEntityManagerFactory(puName, EMF_PROPERTIES);
        }

        @Override
        public EntityManager getEntityManager() {
            return AbstractBaseTest.createEntityManager(puName, EMF_PROPERTIES);
        }

        @Override
        public EntityManagerFactory getEntityManagerFactory() {
            return AbstractBaseTest.getEntityManagerFactory(puName, EMF_PROPERTIES);
        }

        @Override
        public boolean isTransactionActive(EntityManager em) {
            return AbstractBaseTest.this.isTransactionActive(em);
        }

        @Override
        public boolean isTransactionMarkedForRollback(EntityManager em) {
            return AbstractBaseTest.this.getRollbackOnly(em);
        }

        @Override
        public void markTransactionForRollback(EntityManager em) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void rollbackTransaction(EntityManager em) {
            AbstractBaseTest.this.rollbackTransaction(em);
        }

        @Override
        public void rollbackTransactionAndClear(EntityManager em) {
            try {
                rollbackTransaction(em);
            } finally {
                em.clear();
            }
        }

        @Override
        public boolean usesExtendedPC() {
            return true;
        }

        @Override
        public DataSource getDataSource() {
            return AbstractBaseTest.this.getDataSource();
        }

        @Override
        public EntityManagerFactory createNewEntityManagerFactory(Map<String, Object> properties) throws NamingException {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object getPropertyValue(EntityManager em, String key) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void evict(EntityManager em, Class<?> clazz) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void evictAll(EntityManager em) {
            throw new UnsupportedOperationException();
        }

    }

    public DataSource getDataSource() {
        return dataSource;
    }

    final public void closeEntityManager(EntityManager em) {
        if (!em.isOpen()) {
            return;
        }
        if (environment.isTransactionActive(em)/*
                                                * ||environment.
                                                * isTransactionMarkedForRollback
                                                * (em)
                                                */) { // FIXME discuss if tx is
            // active if marked for
            // rollback
            environment.rollbackTransaction(em);
        }
        // // close application-managed entity manager
        // if (!(getEnvironment() instanceof JTASharedPCEnvironment)) {
        // em.close(); FIXME
        // }
    }

    protected static void verify(boolean condition, String string) {
        Assert.assertTrue(string, condition);
    }

    protected final void flop(final String msg) {
        Assert.fail(msg);
    }

    abstract protected String[] getClearableTableNames();

    @Before
    public void clearAllTablesAndSetup() throws SQLException {
        clearAllTables();

        setup();
    }

    protected void clearAllTables() throws SQLException {
        Connection conn = getDataSource().getConnection();
        try {
            conn.setAutoCommit(false);

            Set<String> existingTables = new HashSet<String>();
            DatabaseMetaData metaData = conn.getMetaData();
            String schemaPattern = null;
            if (metaData.getDriverName().toLowerCase().contains("oracle")) {
                schemaPattern = metaData.getUserName().toUpperCase();
            }
            ResultSet rs = metaData.getTables(null, schemaPattern, "TMP_%", null);
            try {
                while (rs.next()) {
                    existingTables.add(rs.getString("TABLE_NAME").toUpperCase(Locale.ENGLISH));
                }
            } finally {
                rs.close();
            }

            Statement statement = conn.createStatement();
            try {
                if (existingTables.contains("TMP_CASC_NODE")) {
                    statement.executeUpdate("update TMP_CASC_NODE set PARENT = null");
                }
                if (existingTables.contains("TMP_NODE")) {
                    statement.executeUpdate("update TMP_NODE set PARENT = null");
                }
                if (existingTables.contains("TMP_COP")) {
                    statement.executeUpdate("update TMP_COP set PARTNER_ID = null");
                }
                if (existingTables.contains("TMP_UCOFFICE_CUBICLE")) {
                    statement.executeUpdate("delete from TMP_UCOFFICE_CUBICLE");
                    existingTables.remove("TMP_UCOFFICE_CUBICLE");
                }
                for (String name : getClearableTableNames()) {
                    if (existingTables.contains(name.toUpperCase(Locale.ENGLISH))) {
                        statement.executeUpdate("delete from " + name);
                    }
                }
            } catch (SQLException ex) {
                System.err.println(ex.getMessage());
                throw ex;
            } finally {
                statement.close();
            }
            conn.commit();
        } finally {
            conn.close();
        }

        // TODO evictAll

    }

    /**
     * intended to be overwritten by subclasses
     */
    protected void setup() throws SQLException {

    }

    public static final <T extends Serializable> T serializeDeserialize(T serializable) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
        try {
            objectOutputStream.writeObject(serializable);
        } finally {
            objectOutputStream.close();
        }
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        return (T) new ObjectInputStream(in).readObject();
    }

    public static boolean isInsideEngine() {
        return false;
    }

    /**
     * Checks whether the given throwable is of type
     * java.lang.IllegalStateException, or otherwise if the throwable contains a
     * java.lang.IllegalStateException somewhere in the cause stack.
     *
     * @param e
     *            The throwable to check
     * @return <code>true</code> if the throwable is instance of or caused by
     *         java.lang.IllegalStateException
     */
    protected final boolean checkForIllegalStateException(Throwable e) {
        boolean contained = false;
        while (e != null) {
            if (e instanceof IllegalStateException) {
                contained = true;
                break;
            }
            e = e.getCause();
        }
        return contained;
    }

    /**
     * Checks whether the given throwable is of type java.sql.SQLException, or
     * otherwise if the throwable contains a java.sql.SQLException somewhere in
     * the cause stack.
     *
     * @param e
     *            The throwable to check
     * @return <code>true</code> if the throwable is instance of or caused by
     *         java.sql.SQLException
     */
    protected final boolean checkForSQLException(Throwable e) {
        boolean contained = false;
        while (e != null) {
            if (e instanceof SQLException) {
                contained = true;
                break;
            }
            e = e.getCause();
        }
        return contained;
    }

    /**
     * Return if the transaction is active. This allows the same code to be used
     * on the server where JTA is used.
     */
    public boolean isTransactionActive(EntityManager entityManager) {
        if (ServerInfoHolder.isOnServer()) {
            return getServerPlatform().isTransactionActive();
        } else {
            return entityManager.getTransaction().isActive();
        }
    }

    /**
     * Return if the transaction is roll back only. This allows the same code to
     * be used on the server where JTA is used.
     */
    public boolean getRollbackOnly(EntityManager entityManager) {
        if (ServerInfoHolder.isOnServer()) {
            return getServerPlatform().getRollbackOnly();
        } else {
            return entityManager.getTransaction().getRollbackOnly();
        }
    }

    /**
     * Begin a transaction on the entity manager. This allows the same code to
     * be used on the server where JTA is used.
     */
    public void beginTransaction(EntityManager entityManager) {
        if (ServerInfoHolder.isOnServer()) {
            getServerPlatform().beginTransaction();
        } else {
            entityManager.getTransaction().begin();
        }
    }

    /**
     * Commit a transaction on the entity manager. This allows the same code to
     * be used on the server where JTA is used.
     */
    public void commitTransaction(EntityManager entityManager) {
        if (ServerInfoHolder.isOnServer()) {
            getServerPlatform().commitTransaction();
        } else {
            entityManager.getTransaction().commit();
        }
    }

    /**
     * Rollback a transaction on the entity manager. This allows the same code
     * to be used on the server where JTA is used.
     */
    public void rollbackTransaction(EntityManager entityManager) {
        if (ServerInfoHolder.isOnServer()) {
            getServerPlatform().rollbackTransaction();
        } else {
            entityManager.getTransaction().rollback();
        }
    }

    /**
     * Return the server platform if running in JEE.
     */
    public static ServerPlatform getServerPlatform() {
        if (serverPlatform == null) {
            serverPlatform = new JEEPlatform();
        }
        return serverPlatform;
    }

    /**
     * Create a new entity manager for the "default" persistence unit. If in JEE
     * this will create or return the active managed entity manager.
     */
    public static EntityManager createEntityManager() {
        if (ServerInfoHolder.isOnServer()) {
            return getServerPlatform().getEntityManager("default");
        } else {
            return getEntityManagerFactory().createEntityManager();
        }
    }

    /**
     * Create a new entity manager for the persistence unit using the
     * properties. The properties will only be used the first time this entity
     * manager is accessed. If in JEE this will create or return the active
     * managed entity manager.
     */
    public static EntityManager createEntityManager(String persistenceUnitName, Map<String, String> properties) {
        if (ServerInfoHolder.isOnServer()) {
            return getServerPlatform().getEntityManager(persistenceUnitName);
        } else {
            return getEntityManagerFactory(persistenceUnitName, properties).createEntityManager();
        }
    }

    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName) {
        return getEntityManagerFactory(persistenceUnitName, JUnitTestCaseHelper.getDatabaseProperties());
    }

    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, Map<String, String> properties) {
        if (ServerInfoHolder.isOnServer()) {
            return getServerPlatform().getEntityManagerFactory(persistenceUnitName);
        } else {
            EntityManagerFactory emfNamedPersistenceUnit = emfNamedPersistenceUnits.get(persistenceUnitName);
            if (emfNamedPersistenceUnit == null) {
                emfNamedPersistenceUnit = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
                emfNamedPersistenceUnits.put(persistenceUnitName, emfNamedPersistenceUnit);
            }
            return emfNamedPersistenceUnit;
        }
    }

    public static EntityManagerFactory getEntityManagerFactory() {
        return getEntityManagerFactory("default");
    }

    public static void closeEntityManagerFactory() {
        closeEntityManagerFactory("default");
    }

    public static void closeEntityManagerFactory(String persistenceUnitName) {
        EntityManagerFactory emfNamedPersistenceUnit = emfNamedPersistenceUnits.get(persistenceUnitName);
        if (emfNamedPersistenceUnit != null) {
            if (emfNamedPersistenceUnit.isOpen()) {
                emfNamedPersistenceUnit.close();
            }
            emfNamedPersistenceUnits.remove(persistenceUnitName);
        }
    }

    public static boolean seesJPA2() {
        return seesJPA2;
    }

    public static Map<String, String> getTestProperties() {
        if (ServerInfoHolder.isOnServer()) {
            return ServerInfoHolder.getTestProperties();
        } else {
            return JUnitTestCaseHelper.getDatabaseProperties();
        }

    }
}
