/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.persistence;

import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.persistence.Parameter;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.ParameterExpression;

import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.persistence.criteria.BindableParameter;

/**
 * An abstract implementation of the Query interface.
 */
public abstract class AbstractQuery<X> implements OpenJPAQuerySPI<X> {
    private static final Localizer _loc = Localizer.forPackage(AbstractQuery.class);

    protected boolean _relaxBindParameterTypeChecking;
    protected boolean _convertPositionalParams;

    // Will be null if this isn't a NamedQuery
    protected final QueryMetaData _qmd;

    protected transient EntityManagerImpl _em;

    protected Map<Parameter<?>, Object> _boundParams;
    protected Map<Object, Parameter<?>> _declaredParams;

    public AbstractQuery(QueryMetaData qmd, EntityManagerImpl em) {
        _qmd = qmd;
        _em = em;

        _boundParams = new HashMap<>();
    }

    /**
     * Gets a map of values of each parameter indexed by their <em>original</em> key.
     *
     * @return an empty map if no parameter is declared for this query. The unbound parameters has a value of null which
     *         is indistinguishable from the value being bound to null.
     */
    Map<Object, Object> getParameterValues() {
        Map<Object, Object> result = new HashMap<>();
        if (_boundParams == null)
            return result;
        for (Map.Entry<Object, Parameter<?>> entry : getDeclaredParameters().entrySet()) {
            Object paramKey = entry.getKey();
            Parameter<?> param = entry.getValue();
            result.put(paramKey, _boundParams.get(param));
        }
        return result;
    }

    public boolean isProcedure() {
        return QueryLanguages.LANG_STORED_PROC.equals(getLanguage());
    }

    public boolean isNative() {
        return QueryLanguages.LANG_SQL.equals(getLanguage());
    }

    protected abstract void assertOpen();

    protected abstract void lock();

    protected abstract void unlock();

   /**
    * @return a map of parameter name to type for this query.
    */
    protected abstract OrderedMap<Object, Class<?>> getParamTypes();

    // =================================================================================
    // Parameter processing routines
    // =================================================================================

    /**
     * Binds the parameter identified by the given position to the given value. The parameter are bound to a value in
     * the context of this query. The same parameter may be bound to a different value in the context of another
     * query. <br>
     * For non-native queries, the given position must be a valid position in the declared parameters. <br>
     * As native queries may not be parsed and hence their declared parameters may not be known, setting an positional
     * parameter has the side-effect of a positional parameter being declared.
     *
     * @param position
     *            positive, integer position of the parameter
     * @param value
     *            an assignment compatible value
     * @return the same query instance
     * @throws IllegalArgumentException
     *             if position does not correspond to a positional parameter of the query or if the argument is of
     *             incorrect type
     */
    @Override
    public OpenJPAQuery<X> setParameter(int pos, Object value) {
        if (_convertPositionalParams) {
            return setParameter("_" + pos, value);
        }

        assertOpen();
        _em.assertNotCloseInvoked();
        lock();
        try {
            if (pos < 1) {
                throw new IllegalArgumentException(_loc.get("illegal-index", pos).getMessage());
            }
            Parameter<?> param;
            if (isNative() || isProcedure()) {
                param = new ParameterImpl<>(pos, Object.class);
                declareParameter(pos, param);
            } else {
                param = getParameter(pos);
            }
            bindValue(param, value);

            return this;
        } finally {
            unlock();
        }
    }

    /**
     * Sets the value of the given positional parameter after conversion of the given value to the given Temporal Type.
     */
    @Override
    public OpenJPAQuery<X> setParameter(int position, Calendar value, TemporalType t) {
        return setParameter(position, convertTemporalType(value, t));
    }

    /**
     * Sets the value of the given named parameter after conversion of the given value to the given Temporal Type.
     */
    @Override
    public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType type) {
        return setParameter(position, convertTemporalType(value, type));
    }

    /**
     * Converts the given Date to a value corresponding to given temporal type.
     */
    Object convertTemporalType(Date value, TemporalType type) {
        switch (type) {
        case DATE:
            return value;
        case TIME:
            return new Time(value.getTime());
        case TIMESTAMP:
            return new Timestamp(value.getTime());
        default:
            return null;
        }
    }

    Object convertTemporalType(Calendar value, TemporalType type) {
        return convertTemporalType(value.getTime(), type);
    }

    /**
     * Affirms if declared parameters use position identifier.
     */
    @Override
    public boolean hasPositionalParameters() {
        return !getDeclaredParameterKeys(Integer.class).isEmpty();
    }

    /**
     * Gets the array of positional parameter values. The n-th array element represents (n+1)-th positional parameter.
     * If a parameter has been declared but not bound to a value then the value is null and hence is indistinguishable
     * from the value being actually null. If the parameter indexing is not contiguous then the unspecified parameters
     * are considered as null.
     */
    @Override
    public Object[] getPositionalParameters() {
        lock();
        try {
            Set<Integer> positionalKeys = getDeclaredParameterKeys(Integer.class);
            Object[] result = new Object[calculateMaxKey(positionalKeys)];
            for (Integer pos : positionalKeys) {
                Parameter<?> param = getParameter(pos);
                result[pos - 1] = isBound(param) ? getParameterValue(pos) : null;
            }
            return result;
        } finally {
            unlock();
        }
    }

    /**
     * Calculate the maximum value of the given set.
     */
    int calculateMaxKey(Set<Integer> p) {
        if (p == null)
            return 0;
        int max = Integer.MIN_VALUE;
        for (Integer i : p)
            max = Math.max(max, i);
        return max;
    }

    /**
     * Binds the given values as positional parameters. The n-th array element value is set to a Parameter with (n+1)-th
     * positional identifier.
     */
    @Override
    public OpenJPAQuery<X> setParameters(Object... params) {
        assertOpen();
        _em.assertNotCloseInvoked();
        lock();
        try {
            clearBinding();
            for (int i = 0; params != null && i < params.length; i++) {
                setParameter(i + 1, params[i]);
            }
            return this;
        } finally {
            unlock();
        }
    }

    void clearBinding() {
        if (_boundParams != null)
            _boundParams.clear();
    }

    /**
     * Gets the value of all the named parameters.
     *
     * If a parameter has been declared but not bound to a value then the value is null and hence is indistinguishable
     * from the value being actually null.
     */
    @Override
    public Map<String, Object> getNamedParameters() {
        lock();
        try {
            Map<String, Object> result = new HashMap<>();
            Set<String> namedKeys = getDeclaredParameterKeys(String.class);
            for (String name : namedKeys) {
                Parameter<?> param = getParameter(name);
                result.put(name, isBound(param) ? getParameterValue(name) : null);
            }
            return result;
        } finally {
            unlock();
        }
    }

    /**
     * Sets the values of the parameters from the given Map. The keys of the given map designate the name of the
     * declared parameter.
     */
    @Override
    public OpenJPAQuery<X> setParameters(Map params) {
        assertOpen();
        _em.assertNotCloseInvoked();
        lock();
        try {
            clearBinding();
            if (params != null) {
                for (Map.Entry e : (Set<Map.Entry>) params.entrySet()) {
                    setParameter((String) e.getKey(), e.getValue());
                }
            }
            return this;
        } finally {
            unlock();
        }
    }

    /**
     * Get the parameter of the given name and type.
     *
     * @throws IllegalArgumentException
     *             if the parameter of the specified name does not exist or is not assignable to the type
     * @throws IllegalStateException
     *             if invoked on a native query
     */
    @Override
    public <T> Parameter<T> getParameter(String name, Class<T> type) {
        Parameter<?> param = getParameter(name);
        if (param.getParameterType().isAssignableFrom(type))
            throw new IllegalArgumentException(param + " does not match the requested type " + type);
        return (Parameter<T>) param;
    }

    /**
     * Get the positional parameter with the given position and type.
     *
     * @throws IllegalArgumentException
     *             if the parameter with the specified position does not exist or is not assignable to the type
     * @throws IllegalStateException
     *             if invoked on a native query unless the same parameter position is bound already.
     */
    @Override
    public <T> Parameter<T> getParameter(int pos, Class<T> type) {
        if (_convertPositionalParams) {
            return getParameter("_" + pos, type);
        }
        Parameter<?> param = getParameter(pos);
        if (param.getParameterType().isAssignableFrom(type))
            throw new IllegalArgumentException(param + " does not match the requested type " + type);
        return (Parameter<T>) param;
    }

    /**
     * Return the value bound to the parameter.
     *
     * @param param
     *            parameter object
     * @return parameter value
     * @throws IllegalStateException
     *             if the parameter has not been been bound
     * @throws IllegalArgumentException
     *             if the parameter does not belong to this query
     */
    @Override
    public <T> T getParameterValue(Parameter<T> p) {
        if (!isBound(p)) {
            throw new IllegalArgumentException(_loc.get("param-missing", p, getQueryString(), getBoundParameterKeys())
                .getMessage());
        }
        return (T) _boundParams.get(p);
    }

    /**
     * Gets the parameters declared in this query.
     */
    @Override
    public Set<Parameter<?>> getParameters() {
        Set<Parameter<?>> result = new HashSet<>(getDeclaredParameters().values());
        return result;
    }

    @Override
    public <T> OpenJPAQuery<X> setParameter(Parameter<T> p, T arg1) {
        bindValue(p, arg1);
        if (BindableParameter.class.isInstance(p)) {
            BindableParameter.class.cast(p).setValue(arg1);
        }
        return this;
    }

    @Override
    public OpenJPAQuery<X> setParameter(Parameter<Date> p, Date date, TemporalType type) {
        return setParameter(p, (Date) convertTemporalType(date, type));
    }

    @Override
    public TypedQuery<X> setParameter(Parameter<Calendar> p, Calendar cal, TemporalType type) {
        return setParameter(p, (Calendar) convertTemporalType(cal, type));
    }

    /**
     * Get the parameter object corresponding to the declared parameter of the given name. This method is not required
     * to be supported for native queries.
     *
     * @throws IllegalArgumentException
     *             if the parameter of the specified name does not exist
     * @throws IllegalStateException
     *             if invoked on a native query
     */
    @Override
    public Parameter<?> getParameter(String name) {
        if (isNative()) {
            throw new IllegalStateException(_loc.get("param-named-non-native", name).getMessage());
        }
        Parameter<?> param = getDeclaredParameters().get(name);
        if (param == null) {
            Set<ParameterExpression> exps = getDeclaredParameterKeys(ParameterExpression.class);
            for (ParameterExpression<?> e : exps) {
                if (name.equals(e.getName()))
                    return e;
            }
            throw new IllegalArgumentException(_loc.get("param-missing-name", name, getQueryString(),
                getDeclaredParameterKeys()).getMessage());
        }
        return param;
    }

    /**
     * Get the positional parameter with the given position. The parameter may just have been declared and not bound to
     * a value.
     *
     * @param position
     *            specified in the user query.
     * @return parameter object
     * @throws IllegalArgumentException
     *             if the parameter with the given position does not exist
     */
    @Override
    public Parameter<?> getParameter(int pos) {
        if (_convertPositionalParams) {
            return getParameter("_" + pos);
        }
        Parameter<?> param = getDeclaredParameters().get(pos);
        if (param == null)
            throw new IllegalArgumentException(_loc.get("param-missing-pos", pos, getQueryString(),
                getDeclaredParameterKeys()).getMessage());
        return param;
    }

    /**
     * Return the value bound to the parameter.
     *
     * @param name
     *            name of the parameter
     * @return parameter value
     *
     * @throws IllegalStateException
     *             if this parameter has not been bound
     */
    @Override
    public Object getParameterValue(String name) {
        return _boundParams.get(getParameter(name));
    }

    /**
     * Return the value bound to the parameter.
     *
     * @param pos
     *            position of the parameter
     * @return parameter value
     *
     * @throws IllegalStateException
     *             if this parameter has not been bound
     */
    @Override
    public Object getParameterValue(int pos) {
        Parameter<?> param = getParameter(pos);
        assertBound(param);
        return _boundParams.get(param);
    }

    /**
     * Gets the parameter keys bound with this query. Parameter key can be Integer, String or a ParameterExpression
     * itself but all parameters keys of a particular query are of the same type.
     */
    public Set<?> getBoundParameterKeys() {
        if (_boundParams == null)
            return Collections.EMPTY_SET;
        getDeclaredParameters();
        Set<Object> result = new HashSet<>();
        for (Map.Entry<Object, Parameter<?>> entry : _declaredParams.entrySet()) {
            if (isBound(entry.getValue())) {
                result.add(entry.getKey());
            }
        }
        return result;
    }

    /**
     * Gets the declared parameter keys in the given query. This information is only available after the query has been
     * parsed. As native language queries are not parsed, this information is not available for them.
     *
     * @return set of parameter identifiers in a parsed query
     */
    public Set<?> getDeclaredParameterKeys() {
        return getDeclaredParameters().keySet();
    }

    public <T> Set<T> getDeclaredParameterKeys(Class<T> keyType) {
        Set<T> result = new HashSet<>();
        for (Object key : getDeclaredParameterKeys()) {
            if (keyType.isInstance(key))
                result.add((T) key);
        }
        return result;
    }

    /**
     * Gets the parameter instances declared in this query. All parameter keys are of the same type. It is not allowed
     * to mix keys of different type such as named and positional keys.
     *
     * For string-based queries, the parser supplies the information about the declared parameters as a LinkedMap of
     * expected parameter value type indexed by parameter identifier. For non string-based queries that a facade itself
     * may construct (e.g. CriteriaQuery), the parameters must be declared by the caller. This receiver constructs
     * concrete Parameter instances from the given parameter identifiers.
     *
     * @return a Map where the key represents the original identifier of the parameter (can be a String, Integer or a
     *         ParameterExpression itself) and the value is the concrete Parameter instance either constructed as a
     *         result of this call or supplied by declaring the parameter explicitly via
     *         {@linkplain #declareParameter(Parameter)}.
     */
    public Map<Object, Parameter<?>> getDeclaredParameters() {
        if (_declaredParams == null) {
            _declaredParams = new HashMap<>();

            OrderedMap<Object, Class<?>> paramTypes = null;
            // Check to see if we have a cached version of the paramTypes in QueryMetaData.
            if (_qmd != null) {
                paramTypes = _qmd.getParamTypes();
            }
            if (paramTypes == null) {
                paramTypes = getParamTypes();
                // Cache the param types as they haven't been set yet.
                if (_qmd != null) {
                    _qmd.setParamTypes(paramTypes);
                }
            }
            for (Entry<Object, Class<?>> entry : paramTypes.entrySet()) {
                Object key = entry.getKey();
                Class<?> expectedValueType = entry.getValue();
                Parameter<?> param;

                if (key instanceof Integer) {
                    param = new ParameterImpl((Integer) key, expectedValueType);
                } else if (key instanceof String) {
                    param = new ParameterImpl((String) key, expectedValueType);
                } else if (key instanceof Parameter) {
                    param = (Parameter<?>) key;
                } else {
                    throw new IllegalArgumentException("parameter identifier " + key + " unrecognized");
                }
                declareParameter(key, param);
            }
        }
        return _declaredParams;
    }

    /**
     * Declares the given parameter for this query. Used by non-string based queries that are constructed by the facade
     * itself rather than OpenJPA parsing the query to detect the declared parameters.
     *
     * @param key
     *            this is the key to identify the parameter later in the context of this query. Valid key types are
     *            Integer, String or ParameterExpression itself.
     * @param the
     *            parameter instance to be declared
     */
    public void declareParameter(Object key, Parameter<?> param) {
        if (_declaredParams == null) {
            _declaredParams = new HashMap<>();
        }
        _declaredParams.put(key, param);
    }

    /**
     * Affirms if the given parameter is bound to a value for this query.
     */
    @Override
    public boolean isBound(Parameter<?> param) {
        return _boundParams != null && _boundParams.containsKey(param);
    }

    void assertBound(Parameter<?> param) {
        if (!isBound(param)) {
            throw new IllegalStateException(_loc.get("param-not-bound", param, getQueryString(),
                getBoundParameterKeys()).getMessage());
        }
    }

    /**
     * Binds the given value to the given parameter. Validates if the parameter can accept the value by its type.
     */
    void bindValue(Parameter<?> param, Object value) {
        Object bindVal = assertValueAssignable(param, value);
        _boundParams.put(param, bindVal);
    }

    @Override
    public OpenJPAQuery<X> setParameter(String name, Calendar value, TemporalType type) {
        return setParameter(name, convertTemporalType(value, type));
    }

    @Override
    public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType type) {
        return setParameter(name, convertTemporalType(value, type));
    }

    /**
     * Sets the parameter of the given name to the given value.
     */
    @Override
    public OpenJPAQuery<X> setParameter(String name, Object value) {
        assertOpen();
        _em.assertNotCloseInvoked();
        lock();
        try {
            // native queries can not have named parameters
            if (isNative()) {
                throw new IllegalArgumentException(_loc.get("no-named-params", name, getQueryString()).toString());
            } else {
                bindValue(getParameter(name), value);
            }

            return this;
        } finally {
            unlock();
        }
    }

    /**
     * Convert the given value to match the given parameter type, if possible.
     *
     * @param param
     *            a query parameter
     * @param v
     *            a user-supplied value for the parameter
     */
    Object assertValueAssignable(Parameter<?> param, Object v) {
        Class<?> expectedType = param.getParameterType();
        if (v == null) {
            if (expectedType.isPrimitive())
                throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
            return v;
        }
        if (getRelaxBindParameterTypeChecking()) {
            try {
                return Filters.convert(v, expectedType);
            } catch (Exception e) {
                throw new IllegalArgumentException(_loc.get("param-type-mismatch",
                    new Object[] { param, getQueryString(), v, v.getClass().getName(), expectedType.getName() })
                    .getMessage());
            }
        } else {
            if (!Filters.canConvert(v.getClass(), expectedType, true)) {
                throw new IllegalArgumentException(_loc.get("param-type-mismatch",
                    new Object[] { param, getQueryString(), v, v.getClass().getName(), expectedType.getName() })
                    .getMessage());
            } else {
                return v;
            }
        }
    }

    // ================== End of Parameter Processing routines ================================

    @Override
    public boolean getRelaxBindParameterTypeChecking() {
        return _relaxBindParameterTypeChecking;
    }

    @Override
    public void setRelaxBindParameterTypeChecking(Object value) {
        if (value != null) {
            if (value instanceof String) {
                _relaxBindParameterTypeChecking = "true".equalsIgnoreCase(value.toString());
            } else if (value instanceof Boolean) {
                _relaxBindParameterTypeChecking = (Boolean) value;
            }
        }
    }
}
