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

import java.util.Calendar;
import java.util.Date;
import java.util.Set;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.Query;
import jakarta.persistence.TemporalType;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;

public abstract class QueryTest extends JPA1Base {

    protected void assertInvalidQueryWithParameters(String queryString, Set<InputParameterHolder> parameters) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            executeQueryWithParameters(queryString, parameters, em);
            message = "Failed to detect invalid query:'" + queryString + "'";
        } catch (IllegalArgumentException IAex) {
            isPassed = true;
            message = IAex.getMessage();
        }
        verify(isPassed, message);
    }

    /**
     */
    private void executeQueryWithParameters(String queryString, Set<InputParameterHolder> parameters, EntityManager em) {
        Query query = em.createQuery(queryString);
        for (InputParameterHolder holder : parameters) {

            setParameterHolder(query, holder);
        }
    }

    /**
     */
    private void setParameterHolder(Query query, InputParameterHolder holder) {
        if (holder.isTemporal()) {
            if (holder.getType() == ParameterType.POSITIONAL) {
                if (holder.getValue() instanceof Date) {
                    query.setParameter((Integer) holder.getIdentitfier(), (Date) holder.getValue(), holder.getTemporalType());
                } else if (holder.getValue() instanceof Calendar) {
                    query.setParameter((Integer) holder.getIdentitfier(), (Calendar) holder.getValue(), holder
                            .getTemporalType());
                }
            } else if (holder.getType() == ParameterType.NAMED) {
                if (holder.getValue() instanceof Date) {
                    query.setParameter((String) holder.getIdentitfier(), (Date) holder.getValue(), holder.getTemporalType());
                } else if (holder.getValue() instanceof Calendar) {
                    query
                            .setParameter((String) holder.getIdentitfier(), (Calendar) holder.getValue(), holder
                                    .getTemporalType());
                }
            }
        } else {
            if (holder.getType() == ParameterType.POSITIONAL) {
                query.setParameter((Integer) holder.getIdentitfier(), holder.getValue());
            } else if (holder.getType() == ParameterType.NAMED) {
                query.setParameter((String) holder.getIdentitfier(), holder.getValue());
            }
        }
    }

    protected void assertValidQueryWithParameters(String queryString, Set<InputParameterHolder> parameters) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            executeQueryWithParameters(queryString, parameters, em);
            message = "Test successfully passed.";
            isPassed = true;
        } catch (IllegalArgumentException IAex) {
            message = IAex.getMessage();
        }
        verify(isPassed, message);
    }

    protected void assertParameterValid(Query query, InputParameterHolder holder) {
        setParameterHolder(query, holder);
    }

    protected void assertParameterInvalid(Query query, InputParameterHolder holder) {
        boolean passed = false;
        try {
            setParameterHolder(query, holder);
        } catch (IllegalArgumentException e) {
            passed = true;
        }
        verify(passed, ("missing IllegalArgumentException"));
    }

    protected void assertValidUpdateExecution(String queryString) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query q = em.createQuery(queryString);
            q.executeUpdate();
            message = "Query '" + queryString + "' was successfully created.";
            isPassed = true;
            getEnvironment().commitTransactionAndClear(em);
        } catch (Exception ex) {
            getEnvironment().rollbackTransactionAndClear(em);
            message = ex.getMessage();
        }
        verify(isPassed, message);
    }

    protected void assertInvalidUpdateExecution(String queryString) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query q = em.createQuery(queryString);
            q.executeUpdate();
            message = "Failed to detect invalid query:'" + queryString + "'";
            getEnvironment().commitTransactionAndClear(em);
        } catch (Exception ex) {
            isPassed = true;
            message = ex.getMessage();
            getEnvironment().rollbackTransactionAndClear(em);
        }
        verify(isPassed, message);
    }

    protected void assertValidQuery(String queryString) {
        EntityManager em = getEnvironment().getEntityManager();
        try {
            em.createQuery(queryString);
        } catch (RuntimeException e) {
            throw new RuntimeException("An exception occurred while creating a query for String >>" + queryString + "<<", e);
        }
    }

    protected void assertInvalidQuery(String queryString) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createQuery(queryString);
            try {
                query.getResultList();

                message = "Failed to detect invalid query:'" + queryString + "'";
            } catch (PersistenceException ex) {
                isPassed = true;
                message = ex.getMessage();
            } catch (DatabaseException ex) { // FIXME
                isPassed = true;
                message = ex.getMessage();
            }
        } catch (IllegalArgumentException IAex) {
            isPassed = true;
            message = IAex.getMessage();
        } catch (QueryException ex) { // FIXME
            isPassed = true;
            message = ex.getMessage();
        }
        verify(isPassed, message);
    }

    protected void assertInvalidQueryExecution(String queryString) {
        boolean isPassed = false;
        String message;
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query q = em.createQuery(queryString);
            q.getResultList();
            message = "Failed to detect invalid query:'" + queryString + "'";
        } catch (Exception ex) {
            isPassed = true;
            message = ex.getMessage();
        }
        verify(isPassed, message);
    }

    protected void assertValidQueryExecution(String queryString) {
        assertValidQueryExecutionWithArgs(queryString, new Object[0]);
    }

    private boolean isUtilDateLike(Object arg) {
        return arg instanceof java.util.Date || arg instanceof java.util.Calendar;
    }

    protected void assertValidQueryExecutionWithArgs(String queryString, Object... args) {
        EntityManager em = getEnvironment().getEntityManager();

        Query q = em.createQuery(queryString);

        // setting arguments
        if (args != null && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
                if (!isUtilDateLike(args[i])) {
                    q.setParameter(i + 1, args[i]);
                } else {
                    throw new IllegalArgumentException(
                            "Currently, for this test-method the use of date-like input parameters is not supported");
                }
            }
        }
        q.getResultList();
    }

    protected enum ParameterType {
        NAMED, POSITIONAL
    }

    protected class InputParameterHolder {
        private boolean isTemporal = false;
        private ParameterType type;
        private final Object identitfier;
        private final Object value;
        private TemporalType temporalType;

        public InputParameterHolder(Object identifier, Object value, TemporalType temporalType) {
            this(identifier, value);
            this.temporalType = temporalType;
            isTemporal = true;
        }

        public InputParameterHolder(Object identifier, Object value) {
            this.identitfier = identifier;
            this.value = value;

            if (identifier instanceof String) {
                type = ParameterType.NAMED;
            } else if (identifier instanceof Integer) {
                type = ParameterType.POSITIONAL;
            } else {
                throw new IllegalArgumentException("InputParameterHolder was created with an illegal identifier: " + identifier
                        + ". Only String and Integer are allowed.");
            }
        }

        public Object getIdentitfier() {
            return identitfier;
        }

        public Object getValue() {
            return value;
        }

        public TemporalType getTemporalType() {
            return temporalType;
        }

        public ParameterType getType() {
            return type;
        }

        public boolean isTemporal() {
            return isTemporal;
        }
    }
}
