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

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import javax.sql.DataSource;

import org.eclipse.persistence.platform.database.SQLServerPlatform;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.Skip;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.BasicTypesPropertyAccess;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

public class BufferReadTest extends JPA1Base {

    private static final long SECONDS = 0;
    private static final Integer KEY = 1;
    private static final Integer MISS = 2;
    private static final boolean PRINTLN = false;
    private EntityManager em;

    @Override
    protected void setup() {
        JPAEnvironment env = getEnvironment();
        em = env.getEntityManager();
        try {
            BasicTypesPropertyAccess data = new BasicTypesPropertyAccess(1);
            data.fill();
            data.setSerializable(null);
            data.setWrapperByteArray2Binary(null);
            data.setWrapperByteArray2Blob(null);
            data.setWrapperByteArray2Longvarbinary(null);
            data.setWrapperCharacterArray2Clob(null);
            data.setWrapperCharacterArray2Varchar(null);
            env.beginTransaction(em);
            Department department = new Department(1, "something");
            em.persist(data);
            em.persist(department);
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testFindOutsideTransaction() {
        Action action = new Action() {
            @Override
            public void run() {
                em.clear();
                em.find(BasicTypesPropertyAccess.class, KEY);
            }

            @Override
            public String description() {
                return "find outside transaction (large, hit)";
            }

            @Override
            public void prepare() {
            }

            @Override
            public void tearDown() {
            }
        };
        doTest(action);
    }

    @Test
    public void testFindOutsideTransactionSmall() {
        Action action = new Action() {
            @Override
            public void run() {
                em.clear();
                em.find(Department.class, KEY);
            }

            @Override
            public String description() {
                return "find outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
            }

            @Override
            public void tearDown() {
            }
        };
        doTest(action);
    }

    @Test
    public void testQueryCompleteOutsideTransactionSmall() {
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                em.clear();
            }

            @Override
            public String description() {
                return "query complete outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
                query = em.createQuery("select d from Department d where d.id = ?1");
                query.setParameter(1, 1);
                query.getSingleResult();
            }

            @Override
            public void tearDown() {
            }
        };
        doTest(action);
    }

    @Test
    public void testQueryExecuteOnlyOutsideTransactionSmall() {
        final JPAEnvironment environment = getEnvironment();
        final EntityManager myEm = environment.getEntityManager();
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                myEm.clear();
                query.getSingleResult();
            }

            @Override
            public String description() {
                return "query execute outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
                getEnvironment().beginTransaction(myEm);
                query = myEm.createQuery("select d from Department d where d.id = ?1");
                query.setParameter(1, 1);
            }

            @Override
            public void tearDown() {
            }

        };
        doTest(action);
    }

    @Test
    public void testQueryExecuteOnlyOutsideTransactionNew() {
        final JPAEnvironment environment = getEnvironment();
        final EntityManager myEm = environment.getEntityManager();
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                myEm.clear();
                query.getSingleResult();
            }

            @Override
            public String description() {
                return "query execute outside transaction (new, hit)";
            }

            @Override
            public void prepare() {
                getEnvironment().beginTransaction(myEm);
                query = myEm
                        .createQuery("select new org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department(d.id, d.name) from Department d where d.id = ?1");
                query.setParameter(1, 1);
            }

            @Override
            public void tearDown() {
                if (getEnvironment().isTransactionActive(myEm)) {
                    myEm.getTransaction().rollback();
                }
                closeEntityManager(myEm);
            }
        };
        doTest(action);
    }

    @Test
    public void testNamedQueryCompleteOutsideTransactionSmall() {
        Action action = new Action() {
            @Override
            public void run() {
                em.clear();
                Query query = em.createNamedQuery("getDepartmentById");
                query.setParameter(1, 1);
                query.getSingleResult();
            }

            @Override
            public String description() {
                return "query named complete outside transaction (small, hit)";
            }

            @Override
            public void tearDown() {
            }

            @Override
            public void prepare() {
            }
        };
        doTest(action);
    }

    @Test
    public void testNamedQueryExecuteOnlyOutsideTransactionSmall() {
        final JPAEnvironment environment = getEnvironment();
        final EntityManager myEm = environment.getEntityManager();
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                myEm.clear();
                query.getSingleResult();
            }

            @Override
            public String description() {
                return "query named execute outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
                getEnvironment().beginTransaction(myEm);
                query = myEm.createNamedQuery("getDepartmentById");
                query.setParameter(1, 1);
            }

            @Override
            public void tearDown() {
            }
        };
        doTest(action);
    }

    @Test
    public void testNativeEntityExecuteOnlyOutsideTransactionSmall() {
        final JPAEnvironment environment = getEnvironment();
        final EntityManager myEm = environment.getEntityManager();
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                myEm.clear();
                query.getSingleResult();
            }

            @Override
            public String description() {
                return "native entity execute outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
                query = myEm.createNativeQuery("select ID, NAME, VERSION from TMP_DEP where ID = 1", Department.class);
            }

            @Override
            public void tearDown() {

            }
        };
        doTest(action);
    }

    @Test
    @Skip(databases=SQLServerPlatform.class)
    public void testNativeFieldsExecuteOnlyOutsideTransactionSmall() {
        final JPAEnvironment environment = getEnvironment();
        final EntityManager myEm = environment.getEntityManager();
        Action action = new Action() {
            Query query;

            @Override
            public void run() {
                myEm.clear();
                Object object = query.getSingleResult();
                Object[] array = (Object[]) object;
                int id = ((Number) array[0]).intValue();
                String name = (String) array[1];
                new Department(id, name);
            }

            @Override
            public String description() {
                return "native fields execute outside transaction (small, hit)";
            }

            @Override
            public void prepare() {
                query = myEm.createNamedQuery("getDepartmentFieldByField1");
            }

            @Override
            public void tearDown() {
            }
        };
        doTest(action);
    }

    @Test
    public void testJDBCBestSmall() throws SQLException {
        final DataSource dataSource = getEnvironment().getDataSource();
        final Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try {
            final PreparedStatement preparedStatement = connection
                    .prepareStatement("select ID, NAME from TMP_DEP where ID = ?");
            try {
                preparedStatement.setInt(1, 1);
                Action action = new Action() {
                    @Override
                    public void run() {
                        try {
                            ResultSet rs = preparedStatement.executeQuery();
                            try {
                                rs.next();
                                new Department(rs.getInt(1), rs.getString(2));
                            } finally {
                                rs.close();
                            }
                        } catch (SQLException e) {
                            throw new RuntimeException(e);
                        }
                    }

                    @Override
                    public void tearDown() {
                    }

                    @Override
                    public String description() {
                        return "JDBC excluding prepare and set (small, hit)";
                    }

                    @Override
                    public void prepare() {
                    }
                };
                doTest(action);
            } finally {
                preparedStatement.close();
            }
        } finally {

            connection.close();
        }
    }

    @Test
    public void testJDBCInclusivePreapreSmall() throws SQLException {
        final DataSource dataSource = getEnvironment().getDataSource();
        final Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try {
            Action action = new Action() {
                @Override
                public void run() {
                    try {
                        final PreparedStatement preparedStatement = connection
                                .prepareStatement("select ID, NAME from TMP_DEP where ID = ?");
                        preparedStatement.setInt(1, 1);
                        try {
                            ResultSet rs = preparedStatement.executeQuery();
                            try {
                                rs.next();
                                new Department(rs.getInt(1), rs.getString(2));
                            } finally {
                                rs.close();
                                connection.commit();
                            }
                        } finally {
                            preparedStatement.close();
                        }
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public void tearDown() {
                }

                @Override
                public String description() {
                    return "JDBC incuding prepare (small, hit)";
                }

                @Override
                public void prepare() {
                }
            };
            doTest(action);
        } finally {

            connection.close();
        }
    }

    private void printRate(String description, int i) {
        // $JL-SYS_OUT_ERR$
        System.out.println(description + ": " + i + " in " + SECONDS + " second[s] (" + ((SECONDS * 1000.0) / i)
                + " milliseconds)");
    }

    @Test
    public void testNotFound() {
        Action action = new Action() {
            @Override
            public void run() {
                em.clear();
                em.find(BasicTypesPropertyAccess.class, MISS);
            }

            @Override
            public String description() {
                return "find outside transaction (miss)";
            }

            @Override
            public void tearDown() {
            }

            @Override
            public void prepare() {
            }
        };
        doTest(action);
    }

    @Test
    public void testFlush() {
        Action action = new Action() {
            @Override
            public void run() {
                em.flush();
            }

            @Override
            public void tearDown() {
            }

            @Override
            public String description() {
                return "flush (unchanged)";
            }

            @Override
            public void prepare() {
            }
        };
        doTest(action);
    }

    private void doTest(Action action) {
        JPAEnvironment env = getEnvironment();
        em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            em.find(BasicTypesPropertyAccess.class, KEY);
            em.find(Department.class, KEY);
            action.prepare();
            long start = System.currentTimeMillis();
            long end = start + 10;
            while (System.currentTimeMillis() < end) {
                action.run(); // 10 ms warmup in order to fill JIT
            }
            start = System.currentTimeMillis();
            end = start + 1000 * SECONDS;
            int i = 0;
            while (System.currentTimeMillis() < end) {
                // for (int j = 0; j < 10; j++) {
                action.run();
                i++;
            }
            if (PRINTLN) {
                printRate(action.description(), i);
            }

        } finally {
            action.tearDown();
            closeEntityManager(em);
        }
    }

    private interface Action {
        void prepare();

        void run();

        void tearDown();

        String description();
    }
}
