/*
 * 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<Parameter<?>, Object>();
    }

    /**
     * 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<Object, Object>();
        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
     */
    public OpenJPAQuery<X> setParameter(int pos, Object value) {
        if (_convertPositionalParams == true) {
            return setParameter("_" + String.valueOf(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<Object>(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.
     */
    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.
     */
    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.
     */
    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.
     */
    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.intValue() - 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.
     */
    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.
     */
    public Map<String, Object> getNamedParameters() {
        lock();
        try {
            Map<String, Object> result = new HashMap<String, Object>();
            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.
     */
    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
     */
    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.
     */
    public <T> Parameter<T> getParameter(int pos, Class<T> type) {
        if (_convertPositionalParams == true) {
            return getParameter("_" + String.valueOf(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
     */
    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.
     */
    public Set<Parameter<?>> getParameters() {
        Set<Parameter<?>> result = new HashSet<Parameter<?>>();
        result.addAll(getDeclaredParameters().values());
        return result;
    }

    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;
    }

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

    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
     */
    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
     */
    public Parameter<?> getParameter(int pos) {
        if (_convertPositionalParams == true) {
            return getParameter("_" + String.valueOf(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
     */
    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
     */
    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<Object>();
        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<T>();
        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<Object, Parameter<?>>();

            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<Object, Parameter<?>>();
        }
        _declaredParams.put(key, param);
    }

    /**
     * Affirms if the given parameter is bound to a value for this query.
     */
    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);
    }

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

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

    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).booleanValue();
            }
        }
    }
}
