package org.implab.gradle.common.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import org.gradle.api.Action;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Provider;

public final class Properties {
    private Properties() {
    }

    public static <K> void mergeMap(MapProperty<K, Object> property, Map<K, Object> map) {
        map.forEach((k, v) -> {
            if (v instanceof Provider<?>)
                property.put(k, (Provider<?>) v);
            else
                property.put(k, v);
        });
    }

    public static <K, V> void mergeMap(MapProperty<K, V> property, Map<K, ?> map, Function<Object, V> mapper) {
        map.forEach((k, v) -> {
            if (v instanceof Provider<?>)
                property.put(k, ((Provider<?>) v).map(mapper::apply));
            else
                property.put(k, mapper.apply(v));
        });
    }

    public static void mergeList(ListProperty<Object> property, Iterable<Object> values) {
        values.forEach(v -> {
            if (v instanceof Provider<?>)
                property.add((Provider<?>) v);
            else
                property.add(v);
        });
    }

    public static <V> void mergeList(ListProperty<V> property, Iterable<Object> values, Function<Object, V> mapper) {
        values.forEach(v -> {
            if (v instanceof Provider<?>)
                property.add(((Provider<?>) v).map(mapper::apply));
            else
                property.add(mapper.apply(v));
        });
    }

    public static <K> void configureMap(MapProperty<K, Object> prop, Action<Map<K, Object>> configure) {
        var map = new HashMap<K, Object>();
        configure.execute(map);
        mergeMap(prop, map);
    }

    public static <K, V> void configureMap(MapProperty<K, V> prop, Action<Map<K, Object>> configure, Function<Object, V> mapper) {
        var map = new HashMap<K, Object>();
        configure.execute(map);
        mergeMap(prop, map, mapper);
    }
}
