/*
 * 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.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.kernel.exps.AggregateListener;
import org.apache.openjpa.kernel.exps.FilterListener;
import org.apache.openjpa.lib.conf.ProductDerivation;
import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringDistance;

/**
 * Manages query hint keys and handles their values on behalf of a owning
 * {@link QueryImpl}. Uses specific knowledge of hint keys declared in
 * different parts of the system.
 * 
 * This receiver collects hint keys from different parts of the system. The
 * keys are implicitly or explicitly declared by several different mechanics.
 * This receiver sets the values on behalf of a owning {@link QueryImpl}
 * based on the its specific knowledge of these keys.
 * 
 * The hint keys from following sources are collected and handled: 
 * 
 * 1. {@link org.apache.openjpa.kernel.QueryHints} interface declares hint keys
 *    as public static final fields. These fields are collected by reflection.
 *    The values are handled by invoking methods on the owning {@link QueryImpl}
 *    
 * 2. Some hint keys are collected from bean-style property names of {@link 
 *    JDBCFetchPlan} by {@link Reflection#getBeanStylePropertyNames(Class) 
 *    reflection} and prefixed with <code>openjpa.FetchPlan</code>. 
 *    Their values are used to set the corresponding property of {@link 
 *    FetchPlan} via {@link #hintToSetter(FetchPlan, String, Object) reflection}
 *      
 * 3. Currently defined <code>javax.persistence.*</code> hint keys have  
 *    a equivalent counterpart to one of these FetchPlan keys. 
 *    The JPA keys are mapped to equivalent FetchPlan hint keys.
 *    
 * 4. Some keys directly invoke setters or add listeners to the owning 
 *    {@link QueryImpl}. These hint keys are statically declared in 
 *    this receiver itself. 
 *    
 * 5. ProductDerivation may introduce their own query hint keys via {@link 
 *    ProductDerivation#getSupportedQueryHints()}. Their values are set in the 
 *    {@link FetchConfiguration#setHint(String, Object)}
 *     
 *  A hint key is classified into one of the following three categories:
 *  
 *  1. Supported: A key is known to this receiver as collected from different 
 *     parts of the system. The value of a supported key is recorded and 
 *     available via {@link #getHints()} method. 
 *  2. Recognized: A key is not known to this receiver but has a prefix which
 *     is known to this receiver. The value of a recognized key is not recorded 
 *     but its value is available via {@link FetchConfiguration#getHint(String)}
 *  3. Unrecognized: A key is neither supported nor recognized. The value of a 
 *     unrecognized key is neither recorded nor set anywhere.
 *  
 *  If an incompatible value is supplied for a supported key, a non-fatal
 *  {@link ArgumentException} is raised.
 *  
 * @author Pinaki Poddar
 *
 * @since 2.0.0
 * 
 */
public class HintHandler  {
  protected final QueryImpl<?> owner;

    private static final Localizer _loc = Localizer.forPackage(HintHandler.class);
    protected static Set<String> _supportedHints = ProductDerivations.getSupportedQueryHints();

    protected static final String PREFIX_OPENJPA = "openjpa.";
    protected static final String PREFIX_JDBC = PREFIX_OPENJPA + "jdbc.";
    protected static final String PREFIX_FETCHPLAN = PREFIX_OPENJPA + "FetchPlan.";
    private Map<String, Object> _hints;

    
    HintHandler(QueryImpl<?> impl) {
        super();
        owner = impl;
    }
    
    /**
     * Record a key-value pair only only if the given key is supported.
     * 
     * @return FALSE if the key is unrecognized. 
     *         null (i.e. MAY BE) if the key is recognized, but not supported.
     *         TRUE if the key is supported.
     */
    protected Boolean record(String hint, Object value) {
        if (hint == null)
            return Boolean.FALSE;
        if (_supportedHints.contains(hint)) {
            if (_hints == null)
                _hints = new TreeMap<String, Object>();
            _hints.put(hint, value);
            return Boolean.TRUE;
        }
        if (isKnownPrefix(hint)) {
            Log log = owner.getDelegate().getBroker().getConfiguration().getLog(OpenJPAConfiguration.LOG_RUNTIME);
            String possible = StringDistance.getClosestLevenshteinDistance(hint, getSupportedHints());
            if (log.isWarnEnabled())
                log.warn(_loc.get("bad-query-hint", hint, possible));
            return null; // possible but not registered
        }
        return Boolean.FALSE; // not possible
    }

    public void setHint(String key, Object value) {
        Boolean status = record(key, value);
        if (Boolean.FALSE.equals(status))
            return;
        FetchPlan plan = owner.getFetchPlan();
        if (status == null) {
            plan.setHint(key, value);
            return;
        }
        
        ClassLoader loader = owner.getDelegate().getBroker().getClassLoader();
        if (QueryHints.HINT_SUBCLASSES.equals(key)) {
            if (value instanceof String)
                value = Boolean.valueOf((String) value);
            owner.setSubclasses(((Boolean) value).booleanValue());
        } else if (QueryHints.HINT_RELAX_BIND_PARAM_TYPE_CHECK.equals(key)) {
            owner.setRelaxBindParameterTypeChecking(value);
        } else if (QueryHints.HINT_FILTER_LISTENER.equals(key)) {
            owner.addFilterListener(Filters.hintToFilterListener(value, loader));
        } else if (QueryHints.HINT_FILTER_LISTENERS.equals(key)) {
            FilterListener[] arr = Filters.hintToFilterListeners(value, loader);
            for (int i = 0; i < arr.length; i++)
                owner.addFilterListener(arr[i]);
        } else if (QueryHints.HINT_AGGREGATE_LISTENER.equals(key)) {
            owner.addAggregateListener(Filters.hintToAggregateListener(value, loader));
        } else if (QueryHints.HINT_AGGREGATE_LISTENERS.equals(key)) {
            AggregateListener[] arr = Filters.hintToAggregateListeners(value, loader);
            for (int i = 0; i < arr.length; i++) {
                owner.addAggregateListener(arr[i]);
            }
        } else if (QueryHints.HINT_RESULT_COUNT.equals(key)) {
            int v = (Integer) Filters.convert(value, Integer.class);
            if (v < 0) {
                throw new IllegalArgumentException(_loc.get("bad-query-hint-value", key, value).toString());
            }
            plan.setHint(key, v);
        } else if (QueryHints.HINT_INVALIDATE_PREPARED_QUERY.equals(key)) {
            plan.setHint(key, Filters.convert(value, Boolean.class));
            owner.invalidatePreparedQuery();
        } else if (QueryHints.HINT_IGNORE_PREPARED_QUERY.equals(key)) {
            plan.setHint(key, Filters.convert(value, Boolean.class));
            owner.ignorePreparedQuery();
        } else if (QueryHints.HINT_USE_LITERAL_IN_SQL.equals(key)) {
            Boolean convertedValue = (Boolean)Filters.convert(value, Boolean.class);
            plan.setHint(key, convertedValue);
        } else { // default 
            plan.setHint(key, value);
        }
    }
    
    /**
     * Affirms if the given key starts with any of the known prefix.
     * @param key
     */
    protected boolean isKnownPrefix(String key) {
        if (key == null)
            return false;
        for (String prefix : ProductDerivations.getConfigurationPrefixes()) {
            if (key.startsWith(prefix))
                return true;
        }
        return false;
    }

    
    
//    protected boolean hasPrecedent(String key) {
//        boolean hasPrecedent = true;
//        String[] list = precedenceMap.get(key);
//        if (list != null) {
//            for (String hint : list) {
//                if (hint.equals(key))
//                    break;
//                // stop if a higher precedence hint has already defined 
//                if (getHints().containsKey(hint)) {
//                    hasPrecedent = false;
//                    break;
//                }
//            }
//        }
//        return hasPrecedent;
//    }

//    private Integer toLockLevel(Object value) {
//        Object origValue = value;
//        if (value instanceof String) {
//            // to accommodate alias name input in relationship with enum values
//            //  e.g. "optimistic-force-increment" == LockModeType.OPTIMISTIC_FORCE_INCREMENT
//            String strValue = ((String) value).toUpperCase().replace('-', '_');
//            value = Enum.valueOf(LockModeType.class, strValue);
//        }
//        if (value instanceof LockModeType)
//            value = MixedLockLevelsHelper.toLockLevel((LockModeType) value);
//
//        Integer intValue = null;
//        if (value instanceof Integer)
//            intValue = (Integer) value;
//        if (intValue == null
//            || (intValue != MixedLockLevels.LOCK_NONE
//                && intValue != MixedLockLevels.LOCK_READ
//                && intValue != MixedLockLevels.LOCK_OPTIMISTIC
//                && intValue != MixedLockLevels.LOCK_WRITE
//                && intValue != MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT
//                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_READ
//                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_WRITE
//                && intValue != MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT)
//                )
//            throw new IllegalArgumentException(_loc.get("bad-lock-level", origValue).getMessage());
//        return intValue;
//    }
    
    /**
     * Gets all the supported hint keys. The set of supported hint keys is
     * statically determined by collecting hint keys from the ProductDerivations.
     */
    public Set<String> getSupportedHints() {
        return _supportedHints;
    }
    
    /**
     * Gets all the recorded hint keys and their values.
     */
    public Map<String, Object> getHints() {
        if (_hints == null)
            return Collections.emptyMap();
        return Collections.unmodifiableMap(_hints);
    }

}

