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

import org.apache.tamaya.Configuration;
import org.apache.tamaya.TypeLiteral;

import java.lang.reflect.AnnotatedElement;
import java.util.*;

/**
 * A conversion context containing all the required values for implementing conversion. Use the included #Builder
 * for creating new instances of. This class is thread-safe to use. Adding supported formats is synchronized.
 * @see PropertyConverter
 */
public class ConversionContext {

    public static final ConversionContext EMPTY = new ConversionContext.Builder(TypeLiteral.of(String.class)).build();
    private final Configuration configuration;
    private final String key;
    private final List<PropertyValue> values;
    private final TypeLiteral<?> targetType;
    private final AnnotatedElement annotatedElement;
    private final Set<String> supportedFormats = new LinkedHashSet<>();

    /**
     * Private constructor used from builder.
     * @param builder the builder, not {@code null}.
     */
    protected ConversionContext(Builder builder){
        this.key = builder.key;
        this.annotatedElement = builder.annotatedElement;
        this.targetType = builder.targetType;
        this.supportedFormats.addAll(builder.supportedFormats);
        this.configuration = builder.configuration;
        List<PropertyValue> tempValues = new ArrayList<>();
        tempValues.addAll(builder.values);
        this.values = Collections.unmodifiableList(tempValues);
    }

    /**
     * Get the key accessed. This information is very useful to evaluate additional metadata needed to determine/
     * control further aspects of the conversion.
     * @return the key. This may be null in case where a default value has to be converted and no unique underlying
     * key/value configuration is present.
     */
    public String getKey(){
        return key;
    }

    /**
     * Get the correspnoding underlying property values matching the given key, in order of significance
     * (most significant last).
     * @return the underlying values evaluated, never null.
     */
    public List<PropertyValue> getValues(){
        return this.values;
    }

    /**
     * Get the target type required.
     * @return the target type required.
     */
    public TypeLiteral<?> getTargetType(){
        return targetType;
    }

    /**
     * Get the annotated element, if conversion is performed using injection mechanisms.
     * @return the annotated element, or {@code null}.
     */
    public AnnotatedElement getAnnotatedElement(){
        return annotatedElement;
    }

    /**
     * Get the configuration, which is targeted.
     * @return the configuration instance, or {@code null}.
     */
    public Configuration getConfiguration(){
        return configuration;
    }


    /**
     * Evaluate the metadata for the current target key from the given values. Later values hereby are more significant.
     * @return the evaluated meta data mapProperties.
     */
    public Map<String, String> getMeta() {
        Map<String, String> metaMap = new HashMap<>();
        if(configuration!=null){
            metaMap.putAll(configuration.getContext().getMetaData(key));
        }
        for(PropertyValue val:values){
            if(key.equals(val.getQualifiedKey())){
                metaMap.putAll(val.getMeta());
            }
        }
        return metaMap;
    }

    /**
     * Allows to addPropertyValue information on the supported/tried formats, which can be shown to the user, especially when
     * conversion failed. Adding of formats is synchronized, all formats are added in order to the overall createList.
     * This means formats should be passed in order of precedence.
     * @param converterType the converters, which implements the formats provided.
     * @param formatDescriptors the format descriptions in a human readable form, e.g. as regular expressions.
     */
    public void addSupportedFormats(@SuppressWarnings("rawtypes") Class<?> converterType, String... formatDescriptors){
        synchronized (supportedFormats){
            for(String format: formatDescriptors) {
                supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
            }
        }
    }

    /**
     * Get the supported/tried formats in precedence order. The contents of this method depends on the
     * {@link PropertyConverter} instances involved in a conversion.
     * @return the supported/tried formats, never {@code null}.
     */
    public List<String> getSupportedFormats(){
        synchronized (supportedFormats){
            return new ArrayList<>(supportedFormats);
        }
    }

    /**
     * Creates a builder based on this instance.
     */
    public Builder toBuilder(){
        Builder builder = new Builder(key, targetType)
                .setConfiguration(this.configuration)
                .setValues(this.values);
        if(annotatedElement!=null) {
            builder.setAnnotatedElement(annotatedElement);
        }
        builder.supportedFormats.addAll(this.supportedFormats);
        return builder;
    }

    @Override
    public String toString() {
        return "ConversionContext{" +
                "configuration=" + configuration +
                ", key='" + key + '\'' +
                ", targetType=" + targetType +
                ", annotatedElement=" + annotatedElement +
                ", supportedFormats=" + supportedFormats +
                '}';
    }

    /**
     * Get the current configuration context.
     * @deprecated Use {@link #getConfiguration()} and {@link Configuration#getContext()}.
     * @return the current configuration context.
     */
    @Deprecated
    public ConfigurationContext getConfigurationContext() {
        if(configuration!=null) {
            return configuration.getContext();
        }
        return ConfigurationContext.EMPTY;
    }

    /**
     * Builder to create new instances of {@link ConversionContext}.
     */
    public static final class Builder{
        /** The backing configuration. */
        private Configuration configuration;
        /** The accessed key, or null. */
        private String key;
        /** The corresponding property values, as delivered from the corresponding property sources,
         * in order of significance (highest last).
         */
        private final List<PropertyValue> values = new ArrayList<>();
        /** The target type. */
        private TypeLiteral<?> targetType;
        /** The injection target (only setCurrent with injection used). */
        private AnnotatedElement annotatedElement;
        /** The ordered setCurrent of formats tried. */
        private final Set<String> supportedFormats = new LinkedHashSet<>();

        /**
         * Creates a new Builder instance.
         * @param targetType the target type
         */
        public Builder(TypeLiteral<?> targetType) {
            this(null,  null, targetType);
        }

        /**
         * Creates a new Builder instance.
         * @param key the requested key, may be null.
         * @param targetType the target type
         */
        public Builder(String key, TypeLiteral<?> targetType) {
            this(null,  key, targetType);
        }

        /**
         * Creates a new Builder instance.
         * @param configuration the configuration, not {@code null}.
         * @param key the requested key, may be {@code null}.
         * @param targetType the target type
         */
        public Builder(Configuration configuration, String key, TypeLiteral<?> targetType){
            this.key = key;
            this.configuration = configuration;
            this.targetType = Objects.requireNonNull(targetType);
        }

        /**
         * Sets the key.
         * @param key the key, not {@code null}.
         * @return the builder instance, for chaining
         */
        public Builder setKey(String key){
            this.key = Objects.requireNonNull(key);
            return this;
        }

        /**
         * Sets the underlying values evaluated.
         * @param values the values, not {@code null}.
         * @return the builder instance, for chaining
         */
        public Builder setValues(List<PropertyValue> values){
            this.values.addAll(values);
            return this;
        }

        /**
         * Sets the underlying values evaluated.
         * @param values the values, not {@code null}.
         * @return the builder instance, for chaining
         */
        public Builder setValues(PropertyValue... values){
            this.values.addAll(Arrays.asList(values));
            return this;
        }

        /**
         * Sets the configuration.
         * @param configuration the configuration, not {@code null}
         * @return the builder instance, for chaining
         */
        public Builder setConfiguration(Configuration configuration){
            this.configuration = Objects.requireNonNull(configuration);
            return this;
        }

        /**
         * Sets the annotated element, when configuration is injected.
         * @param annotatedElement the annotated element, not {@code null}
         * @return the builder instance, for chaining
         */
        public Builder setAnnotatedElement(AnnotatedElement annotatedElement){
            this.annotatedElement = Objects.requireNonNull(annotatedElement);
            return this;
        }

        /**
         * Sets the target type explicitly. This is required in some rare cases, e.g. injection of {@code Provider}
         * instances, where the provider's result type must be produced.
         * @param targetType the
         * @return the builder for chaining.
         */
        public Builder setTargetType(@SuppressWarnings("rawtypes") TypeLiteral targetType) {
            this.targetType = Objects.requireNonNull(targetType);
            return this;
        }

        /**
         * Add the formats provided by a {@link PropertyConverter}. This method should be called by each converters
         * performing/trying conversion, so the user can be given feedback on the supported formats on failure.
         * @param converterType the converters type, not {@code null}.
         * @param formatDescriptors the formats supported in a human readable form, e.g. as regular expressions.
         * @return the builder instance, for chaining
         */
        public Builder addSupportedFormats(@SuppressWarnings("rawtypes") Class<?> converterType, String... formatDescriptors){
            for(String format: formatDescriptors) {
                supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
            }
            return this;
        }

        /**
         * Builds a new context instance.
         * @return a new context, never null.
         */
        public ConversionContext build(){
            return new ConversionContext(this);
        }

        @Override
        public String toString() {
            return "Builder{" +
                    "configuration=" + configuration +
                    ", key='" + key + '\'' +
                    ", targetType=" + targetType +
                    ", annotatedElement=" + annotatedElement +
                    ", supportedFormats=" + supportedFormats +
                    '}';
        }

    }
}
