/*
* 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.stanbol.enhancer.ldpath.function;

import static java.util.Collections.singletonMap;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;

import org.apache.clerezza.rdf.core.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import at.newmedialab.ldpath.api.backend.RDFBackend;
import at.newmedialab.ldpath.api.functions.SelectorFunction;
import at.newmedialab.ldpath.api.selectors.NodeSelector;
import at.newmedialab.ldpath.model.transformers.IntTransformer;
import at.newmedialab.ldpath.model.transformers.StringTransformer;


public class SuggestionFunction implements SelectorFunction<Resource> {
    
    private static final Comparator<Entry<Double,Resource>> SUGGESTION_COMPARATOR = 
            new Comparator<Entry<Double,Resource>>() {

        @Override
        public int compare(Entry<Double,Resource> e1, Entry<Double,Resource> e2) {
            return e2.getKey().compareTo(e1.getKey());
        }
        
    };
    private static final int MISSING_CONFIDENCE_FIRST = -1;
    private static final int MISSING_CONFIDENCE_FILTER = 0;
    private static final int MISSING_CONFIDENCE_LAST = -1;
    private static final int DEFAULT_MISSING_CONFIDENCE_MODE = MISSING_CONFIDENCE_FILTER;
    private static final Double MAX = Double.valueOf(Double.POSITIVE_INFINITY);
    private static final Double MIN = Double.valueOf(Double.NEGATIVE_INFINITY);
//    private static final String ANNOTATION_PROCESSING_MODE_SINGLE = "single";
//    private static final String ANNOTATION_PROCESSING_MODE_UNION = "union";
//    private static final String DEFAULT_ANNOTATION_PROCESSING_MODE = ANNOTATION_PROCESSING_MODE_SINGLE;

    Logger log = LoggerFactory.getLogger(SuggestionFunction.class);

    private final String name;
    private final IntTransformer<Resource> intTransformer;
    private final StringTransformer<Resource> stringTransformer;
    private final NodeSelector<Resource> suggestionSelector;
    private final NodeSelector<Resource> confidenceSelector;
    private final NodeSelector<Resource> resultSelector;
    public SuggestionFunction(String name,
                              NodeSelector<Resource> suggestionSelector,
                              NodeSelector<Resource> confidenceSelector){
        this(name,null,suggestionSelector,confidenceSelector);
    }
    public SuggestionFunction(String name,
                              NodeSelector<Resource> suggestionSelector,
                              NodeSelector<Resource> confidenceSelector,
                              NodeSelector<Resource> resultSelector) {
        intTransformer = new IntTransformer<Resource>();
        stringTransformer = new StringTransformer<Resource>();
        if(name == null || name.isEmpty()){
            throw new IllegalArgumentException("The parsed function name MUST NOT be NULL nor empty!");
        }
        this.name = name;
        if(suggestionSelector == null){
            throw new IllegalArgumentException("The NodeSelector used to select the Suggestions for the parsed Context MUST NOT be NULL!");
        }
        this.suggestionSelector = suggestionSelector;
        if(confidenceSelector == null){
            throw new IllegalArgumentException("The NodeSelector used to select the Confidence for Suggestions MUST NOT be NULL!");
        }
        this.confidenceSelector = confidenceSelector;
        this.resultSelector = resultSelector;
    }
    
    @Override
    public Collection<Resource> apply(final RDFBackend<Resource> backend, Resource context, Collection<Resource>... args) throws IllegalArgumentException {
        Integer limit = parseParamLimit(backend, args,1);
//        final String processingMode = parseParamProcessingMode(backend, args,2);
        final int missingConfidenceMode = parseParamMissingConfidenceMode(backend, args,2);
        List<Resource> result = new ArrayList<Resource>();
//        if(processingMode.equals(ANNOTATION_PROCESSING_MODE_UNION)){
            processAnnotations(backend, args[0], limit, missingConfidenceMode, result);
//        } else {
//            for(Resource context : args[0]){
//                processAnnotations(backend, singleton(context),
//                    limit, missingConfidenceMode, result);
//            }
//        }
        return result;
    }
    /**
     * Suggestions are selected by all Annotations returned by the parsed
     * {@link #annotationSelector}.
     * @param backend
     * @param annotations suggestions are selected for the union of the parsed
     * annotations - the {limit} most linked entities for the parsed
     * list of annotations.
     * @param limit the maximum number of suggestions for the parsed collection
     * of annotations.
     * @param missingConfidenceMode
     * @param result results are added to this list.
     */
    private void processAnnotations(final RDFBackend<Resource> backend,
                                    Collection<Resource> annotations,
                                    Integer limit,
                                    final int missingConfidenceMode,
                                    List<Resource> result) {
        List<Entry<Double,Resource>> suggestions = new ArrayList<Entry<Double,Resource>>();
        for(Resource annotation : annotations){
            for(Resource suggestion : suggestionSelector.select(backend, annotation, null, null)){
                Collection<Resource> cs = confidenceSelector.select(backend, suggestion, null, null);
                Double confidence = !cs.isEmpty() ? backend.doubleValue(cs.iterator().next()) : 
                        missingConfidenceMode == MISSING_CONFIDENCE_FILTER ?
                                null : missingConfidenceMode == MISSING_CONFIDENCE_FIRST ?
                                        MAX : MIN;
                if(confidence != null){
                    suggestions.add(singletonMap(confidence,suggestion).entrySet().iterator().next());

                }
            }
        }
        Collections.sort(suggestions, SUGGESTION_COMPARATOR);
        int resultSize = limit != null ? Math.min(limit, suggestions.size()) : suggestions.size();
        for(Entry<Double,Resource> suggestion : suggestions.subList(0, resultSize)){
            if(resultSelector == null){
                result.add(suggestion.getValue());
            } else {
                result.addAll(resultSelector.select(backend, suggestion.getValue(), null, null));
            }
        }
    }
    /*
     * Helper Method to parse the parameter
     */
    /**
     * @param backend
     * @param args
     * @return
     */
    private int parseParamMissingConfidenceMode(final RDFBackend<Resource> backend,
                                                Collection<Resource>[] args, int index) {
        final int missingConfidenceMode;
        if(args.length > index && !args[index].isEmpty()){
            String mode = stringTransformer.transform(backend, args[index].iterator().next());
            if("first".equalsIgnoreCase(mode)){
                missingConfidenceMode = MISSING_CONFIDENCE_FIRST;
            } else if("last".equalsIgnoreCase(mode)){
                missingConfidenceMode = MISSING_CONFIDENCE_LAST;
            } else if("filter".equalsIgnoreCase(mode)){
                missingConfidenceMode = MISSING_CONFIDENCE_FILTER;
            } else {
                missingConfidenceMode = DEFAULT_MISSING_CONFIDENCE_MODE;
                log.warn("Unknown value for parameter 'missing confidence value mode' '{}'" +
                		"(supported: 'first','last','filter') use default: 'filter')",mode);
            }
        } else {
            missingConfidenceMode = DEFAULT_MISSING_CONFIDENCE_MODE;
        }
        return missingConfidenceMode;
    }
//    /**
//     * @param backend
//     * @param args
//     * @return
//     */
//    private String parseParamProcessingMode(final RDFBackend<Resource> backend, Collection<Resource>[] args, int index) {
//        final String processingMode;
//        if(args.length > index && !args[index].isEmpty()){
//            String mode = stringTransformer.transform(backend, args[index].iterator().next());
//            if(ANNOTATION_PROCESSING_MODE_SINGLE.equalsIgnoreCase(mode)){
//                processingMode = ANNOTATION_PROCESSING_MODE_SINGLE;
//            } else if(ANNOTATION_PROCESSING_MODE_UNION.equalsIgnoreCase(mode)) {
//                processingMode = ANNOTATION_PROCESSING_MODE_UNION;
//            } else {
//                processingMode = DEFAULT_ANNOTATION_PROCESSING_MODE;
//                log.warn("Unknown value for parameter 'annotation processing mode' '{}'" +
//                        "(supported: 'single','union') default: 'single')",mode);
//            }
//        } else {
//            processingMode = DEFAULT_ANNOTATION_PROCESSING_MODE;
//        }
//        return processingMode;
//    }
    /**
     * @param backend
     * @param args
     * @return
     */
    private Integer parseParamLimit(final RDFBackend<Resource> backend, Collection<Resource>[] args,int index) {
        Integer limit = null;
        if(args.length > index && !args[index].isEmpty()){
            Resource value = args[index].iterator().next();
            try {
                limit = intTransformer.transform(backend, value);
                if(limit < 1){
                    limit = null;
                }
            } catch (RuntimeException e) {
                log.warn("Unable to parse parameter 'limit' form the 2nd argument '{}'",value);
            }
        }
        return limit;
    }


    @Override
    public String getPathExpression(RDFBackend<Resource> backend) {
        return name;
    }

	@Override
	public String getSignature() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return null;
	}

    
}
