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

import java.util.Arrays;
import java.util.Collection;
import org.opengis.util.ScopedName;
import org.apache.sis.util.ObjectConverter;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.UnconvertibleObjectException;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.feature.builder.PropertyTypeBuilder;
import org.apache.sis.feature.builder.AttributeTypeBuilder;
import org.apache.sis.internal.feature.FeatureExpression;
import org.apache.sis.util.resources.Errors;

// Branch-dependent imports
import org.apache.sis.feature.DefaultFeatureType;


/**
 * Expression whose results are converted to a different type.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.2
 *
 * @param  <R>  the type of resources (e.g. {@code Feature}) used as inputs.
 * @param  <S>  the type of value computed by the wrapped exception. This is the type to convert.
 * @param  <V>  the type of value computed by this expression. This is the type after conversion.
 *
 * @see org.apache.sis.internal.filter.GeometryConverter
 *
 * @since 1.1
 * @module
 */
final class ConvertFunction<R,S,V> extends UnaryFunction<R,S>
        implements FeatureExpression<R,V>, Optimization.OnExpression<R,V>
{
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 4686604324414717316L;

    /**
     * Name of this expression.
     */
    private static final ScopedName NAME = createName("Convert");

    /**
     * The converter to use.
     */
    private final ObjectConverter<? super S, ? extends V> converter;

    /**
     * Creates a new converted expression.
     *
     * @param  expression  the expression providing source values.
     * @param  source      the type of value produced by given expression
     * @param  target      the desired type for the expression result.
     * @throws UnconvertibleObjectException if no converter is found.
     */
    ConvertFunction(final Expression<? super R, ? extends S> expression, final Class<S> source, final Class<V> target) {
        super(expression);
        converter = ObjectConverters.find(source, target);
    }

    /**
     * Creates a new converted expression after optimization.
     *
     * @param  expression  the expression providing source values.
     * @throws UnconvertibleObjectException if no converter is found.
     */
    private ConvertFunction(final ConvertFunction<R,S,V> original, final Expression<? super R, ? extends S> expression) {
        super(expression);
        converter = original.converter;
    }

    /**
     * Creates a new expression of the same type than this expression, but with optimized parameters.
     */
    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Expression<R,V> recreate(Expression<? super R, ?>[] effective) {
        final Expression<? super R, ?> e = effective[0];
        if (e instanceof FeatureExpression<?,?>) {
            final Class<? extends V> target = getValueClass();                          // This is <V>.
            final Class<?> source = ((FeatureExpression<?,?>) e).getValueClass();       // May become <S>.
            if (target.isAssignableFrom(source)) {
                return (Expression<R,V>) e;
            }
            if (source != Object.class) {
                return new ConvertFunction(e, source, target);
            }
        }
        final Class<? super S> source = converter.getSourceClass();
        return new ConvertFunction(this, e.toValueType(source));
    }

    /**
     * Returns an identification of this operation.
     */
    @Override
    public ScopedName getFunctionName() {
        return NAME;
    }

    /**
     * Returns the singleton expression tested by this operator
     * together with the source and target classes.
     */
    @Override
    protected Collection<?> getChildren() {
        return Arrays.asList(expression, converter.getSourceClass(), converter.getTargetClass());
    }

    /**
     * Evaluates the expression for producing a result of the given type.
     * If this method can not produce a value of the given type, then it returns {@code null}.
     * This implementation evaluates the expression {@linkplain Expression#apply(Object) in the default way},
     * then tries to convert the result to the target type.
     *
     * @param  feature  the value or feature to evaluate with this expression.
     * @return the result, or {@code null} if it can not be of the specified type.
     */
    @Override
    public V apply(final R feature) {
        final S value = expression.apply(feature);
        try {
            return converter.apply(value);
        } catch (UnconvertibleObjectException e) {
            warning(e, false);
            return null;
        }
    }

    /**
     * Returns the type of values computed by this expression.
     */
    @Override
    public Class<? extends V> getValueClass() {
        return converter.getTargetClass();
    }

    /**
     * Provides the type of values produced by this expression when a feature of the given type is evaluated.
     * May return {@code null} if the type can not be determined.
     */
    @Override
    public PropertyTypeBuilder expectedType(final DefaultFeatureType valueType, final FeatureTypeBuilder addTo) {
        final FeatureExpression<?,?> fex = FeatureExpression.castOrCopy(expression);
        if (fex == null) {
            return null;
        }
        final PropertyTypeBuilder p = fex.expectedType(valueType, addTo);
        if (p instanceof AttributeTypeBuilder<?>) {
            return ((AttributeTypeBuilder<?>) p).setValueClass(getValueClass());
        }
        return p;
    }

    /**
     * Returns an expression doing the same evaluation than this method, but returning results as values
     * of the specified type. The result may be {@code this}.
     *
     * @param  <N>     compile-time value of {@code type}.
     * @param  target  desired type of expression results.
     * @return expression doing the same operation this this expression but with results of the specified type.
     * @throws ClassCastException if the specified type is not a target type supported by implementation.
     */
    @Override
    @SuppressWarnings("unchecked")
    public <N> Expression<R,N> toValueType(final Class<N> target) {
        if (target.isAssignableFrom(getValueClass())) {
            return (Expression<R,N>) this;
        }
        final Class<? super S> source = converter.getSourceClass();
        if (target.isAssignableFrom(source)) {
            return (Expression<R,N>) expression;
        } else try {
            return new ConvertFunction<>(expression, source, target);
        } catch (UnconvertibleObjectException e) {
            throw (ClassCastException) new ClassCastException(Errors.format(
                    Errors.Keys.CanNotConvertValue_2, expression.getFunctionName(), target)).initCause(e);
        }
    }
}
