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

import org.apache.tamaya.spi.ConfigChangeSetCallback;
import org.apache.tamaya.spi.ConfigurationFactorySpi;
import org.apache.tamaya.spi.ConfigurationSpi;
import org.apache.tamaya.spi.ServiceContext;

import java.util.*;
import java.util.function.Function;
import java.util.function.UnaryOperator;

/**
 * A configuration models a aggregated set current properties, identified by a unique key, but adds higher level access functions to
 * a {@link PropertySource}. Hereby in most cases a configuration is a wrapper around a composite
 * {@link PropertySource} instance, which may combine multiple child config in well defined tree like structure,
 * where nodes define logically the rules current priority, filtering, combination and overriding.
 * <br/>
 * <h3>Implementation Requirements</h3>
 * Implementations current this interface must be
 * <ul>
 * <li>Thread safe.
 * <li>Immutable
 * </ul>
 * It is not recommended that implementations also are serializable, since the any configuration can be <i>freezed</i>
 * by reading out its complete configuration map into a serializable and remotable structure. This helps significantly
 * simplifying the development current this interface, e.g. for being backed up by systems and stores that are not part current
 * this library at all.
 */
public interface Configuration extends PropertyMapSupplier,PropertySource {

    /**
     * An empty and immutable Configuration instance.
     */
    public static final Configuration EMPTY_CONFIGURATION = new Configuration() {

        @Override
        public String getName() {
            return "<empty>";
        }

        @Override
        public Optional<String> get(String key) {
            return Optional.empty();
        }

        @Override
        public void update(ConfigChangeSet changeSet) {

        }

        @Override
        public void registerForUpdate(ConfigChangeSetCallback callback) {

        }

        @Override
        public void removeForUpdate(ConfigChangeSetCallback callback) {

        }

        @Override
        public Map<String, String> getProperties() {
            return Collections.emptyMap();
        }

        @Override
        public String toString(){
            return "Configuration [name=<empty>]";
        }
    };

    /**
     * Get the name of the property source. The name should be unique for the type of source, whereas the id is used
     * to ensure unique identity, either locally or remotely.
     * @return the configuration's name, never null.
     */
    String getName();

    /**
     * Access a property.
     *
     * @param key the property's key, not null.
     * @return the property's keys.
     */
    Optional<String> get(String key);

    /**
     * Determines if this config source should be scanned for its list of properties.
     *
     * Generally, slow ConfigSources should return false here.
     *
     * @return true if this ConfigSource should be scanned for its list of properties,
     * false if it should not be scanned.
     */
    default boolean isScannable(){
        return true;
    }

    /**
     * Allows to quickly check, if a provider is empty.
     *
     * @return true, if the provier is empty.
     */
    default boolean isEmpty() {
        return getProperties().isEmpty();
    }

    /**
     * Get the property keys as {@link Boolean}.
     *
     * @param key the property's absolute, or relative path, e.g. {@code
     *            a/b/c/d.myProperty}.
     * @return the property's keys.
     * @throws ConfigException if the configured value could not be converted to the target type.
     */
	default Boolean getBoolean(String key) {
		Optional<Boolean> val = get(key, Boolean.class);
		if (val.isPresent()) {
			return val.get();
		}
		return null;
	}

    /**
     * Get the property keys as {@link Integer}.
     *
     * @param key the property's absolute, or relative path, e.g. @code
     *            a/b/c/d.myProperty}.
     * @return the property's keys.
     * @throws ConfigException if the configured value could not be converted to the target type.
     */
    default OptionalInt getInteger(String key){
        Optional<Integer> val = get(key, Integer.class);
        if(val.isPresent()){
            return OptionalInt.of(val.get());
        }
        return OptionalInt.empty();
    }


    /**
     * Get the property keys as {@link Long}.
     *
     * @param key the property's absolute, or relative path, e.g. @code
     *            a/b/c/d.myProperty}.
     * @return the property's keys.
     * @throws ConfigException if the configured value could not be converted to the target type.
     */
    default OptionalLong getLong(String key){
        Optional<Long> val = get(key, Long.class);
        if(val.isPresent()){
            return OptionalLong.of(val.get());
        }
        return OptionalLong.empty();
    }


    /**
     * Get the property keys as {@link Double}.
     *
     * @param key the property's absolute, or relative path, e.g. @code
     *            a/b/c/d.myProperty}.
     * @return the property's keys.
     * @throws ConfigException if the configured value could not be converted to the target type.
     */
    default OptionalDouble getDouble(String key){

        Optional<Double> val = get(key, Double.class);
        if(val.isPresent()){
            return OptionalDouble.of(val.get());
        }
        return OptionalDouble.empty();
    }


    /**
     * Get the property keys as type {@code Class<T>}.
     * <p>
     * If {@code Class<T>} is not one current
     * {@code Boolean, Short, Integer, Long, Float, Double, BigInteger,
     * BigDecimal, String} , an according adapter must be
     * available to perform the conversion fromMap {@link String} to
     * {@code Class<T>}.
     *
     * @param key     the property's absolute, or relative path, e.g. @code
     *                a/b/c/d.myProperty}.
     * @param adapter the PropertyAdapter to perform the conversion fromMap
     *                {@link String} to {@code Class<T>}, not {@code null}.
     * @return the property's keys.
     * @throws ConfigException if the keys could not be converted to the required target
     *                                  type, or no such property exists.
     */
    default <T> Optional<T> getAdapted(String key, PropertyAdapter<T> adapter){
        Optional<String> value = get(key);
        if(value.isPresent()) {
            return Optional.ofNullable(adapter.adapt(value.get()));
        }
        return Optional.empty();
    }

//    /**
//     * Get the property with the given key as type {@code Class<T>}.
//     * <p>
//     * If {@code Class<T>} is not one current
//     * {@code Boolean, Short, Integer, Long, Float, Double, BigInteger,
//     * BigDecimal, String} , an according adapter must be
//     * available to perform the conversion from {@link String} to
//     * {@code Class<T>}.
//     *
//     * @param key     the property's absolute, or relative path, e.g. {@code
//     *                a/b/c/d.myProperty}.
//     * @param adapter the PropertyAdapter to perform the conversion from
//     *                {@link String} to {@code Class<T>}, not {@code null}.
//     * @return the property value, never null.
//     * @throws ConfigException if the keys could not be converted to the required target
//     *                                  type, or no such property exists.
//     */
//    default <T> DynamicValue<T> getAdaptedDynamicValue(String key, PropertyAdapter<T> adapter){
//        Optional<String> value = get(key);
//        if(value.isPresent()) {
//            return DynamicValue.ofNullable(getName()+':' + key, adapter.adapt(value.get()));
//        }
//        return DynamicValue.empty(getName()+':' + key);
//    }


    /**
     * Get the property keys as type T. This will implicitly require a corresponding {@link
     * PropertyAdapter} to be available that is capable current providing type T
     * fromMap the given String keys.
     *
     * @param key          the property's absolute, or relative path, e.g. @code
     *                     a/b/c/d.myProperty}.
     * @param type         The target type required, not null.
     * @return the property value, never null..
     * @throws ConfigException if the keys could not be converted to the required target
     *                                  type.
     */
    default <T> Optional<T> get(String key, Class<T> type){
        return getAdapted(key, PropertyAdapter.getInstance(type));
    }

//    /**
//     * Get the property value as {@link org.apache.tamaya.DynamicValue}. This will implicitly require a corresponding {@link
//     * PropertyAdapter} that is capable of converting the String value to the current required type T.
//     *
//     * @param key          the property's absolute, or relative path, e.g. {@code
//     *                     a/b/c/d.myProperty}.
//     * @param type         The target type required, not null.
//     * @return the dynamic value instance, never null.
//     * @throws ConfigException if the keys could not be converted to the required target
//     *                                  type.
//     */
//    default <T> DynamicValue<T> getDynamicValue(String key, Class<T> type){
//        return getAdaptedDynamicValue(key, PropertyAdapter.getInstance(type));
//    }

    /**
     * Extension point for adjusting configuration.
     *
     * @param operator A configuration operator, e.g. a filter, or an adjuster
     *                 combining configurations.
     * @return the new adjusted configuration, never {@code null}.
     */
    default PropertySource with(UnaryOperator<PropertySource> operator){
        return operator.apply(this);
    }


    /**
     * Query a configuration.
     *
     * @param query the query, never {@code null}.
     * @return the result
     */
    default <T> T query(Function<PropertySource,T> query){
        return query.apply(this);
    }


    /**
     * Allows to check if a configuration with a given name is defined.
     *
     * @param name the configuration's name, not null, not empty.
     * @return true, if such a configuration is defined.
     */
    public static boolean isAvailable(String name){
        return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).isConfigurationAvailable(name);
    }

    /**
     * Creates a configuration from a {@link org.apache.tamaya.PropertySource}.
     *
     * @param propertySource the property source
     * @return the corresponding Configuration instance, never null.
     */
    public static Configuration from(PropertySource propertySource){
        return ServiceContext.getInstance().getSingleton(ConfigurationFactorySpi.class, () -> new ConfigurationFactorySpi(){}).from(propertySource);
    }

    /**
     * Access a configuration by name.
     *
     * @param name the configuration's name, not null, not empty.
     * @return the corresponding Configuration instance, never null.
     * @throws ConfigException if no such configuration is defined.
     */
    public static Configuration current(String name){
        return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).getConfiguration(name);
    }

    /**
     * Access a configuration.
     *
     * @return the corresponding Configuration instance, never null.
     * @throws ConfigException if no such configuration is defined.
     */
    public static Configuration current(){
        return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).getConfiguration();
    }

    /**
     * Access a typed configuration, based on the default configuration.
     *
     * @param type the annotated configuration type (could be an interface or
     *             a non abstract class), not null.
     * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null.
     *                       If no such config is passed, the default configurationa provided by the current
     *                       registered providers are used.
     * @return the corresponding typed Configuration instance, never null.
     * @throws ConfigException if the configuration could not be resolved.
     */
    public static <T> T createTemplate(Class<T> type, Configuration... configurations){
        return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).createTemplate(type, configurations);
    }

    /**
     * Configures an instance, by resolving and injecting the configuration
     * entries.
     *
     * @param instance the instance with configuration annotations, not null.
     * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null.
     *                       If no such config is passed, the default configurationa provided by the current
     *                       registered providers are used.
     * @throws ConfigException if the configuration could not be resolved.
     */
    public static void configure(Object instance, Configuration... configurations){
        ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).configure(instance, configurations);
    }

    /**
     * Evaluate the current expression based on the current configuration valid.
     *
     * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null.
     *                       If no such config is passed, the default configurationa provided by the current
     *                       registered providers are used.
     * @param expression the expression, not null.
     * @return the evaluated config expression.
     */
    public static String evaluateValue(String expression, Configuration... configurations){
        return ServiceContext.getInstance().getSingleton(ConfigurationSpi.class).evaluateValue(expression, configurations);
    }

}
