package net.ranides.assira.system;

import lombok.experimental.UtilityClass;

import java.io.File;

@UtilityClass
public class RuntimeConfiguration {

    private static final String FEATURE_CACHE_DAEMON = "assira.feature:cache-daemon";

    private static final String FEATURE_CASE_SENSITIVE_FILES = "assira.feature:case-sensitive-files";

    private static final String FEATURE_STRICT_REFLECTIVE_RESOLVE = "assira.feature:strict-reflective-resolve";

    private static final String FIX_FLAT_STREAM = "assira.fix:java.util.stream.Stream#flatMap";

    private static final String FIX_FILES_WALKER = "assira.fix:java.nio.file.Files.newDirectoryStream";

    private static final boolean FEATURE_CACHE_DAEMON_VALUE =
        getBoolean(FEATURE_CACHE_DAEMON, false);

    private static final boolean FIX_FLAT_STREAM_VALUE =
        getBoolean(FIX_FLAT_STREAM, RuntimeUtils.getJavaVersion() <= 11);

    private static final boolean FIX_FILES_WALKER_VALUE =
        getBoolean(FIX_FILES_WALKER, RuntimeUtils.getJavaVersion() <= 7);

    private static final boolean FEATURE_CASE_SENSITIVE_FILES_VALUE =
        getBoolean(FEATURE_CASE_SENSITIVE_FILES, !new File( "a" ).equals( new File( "A" )));

    private static final boolean FEATURE_STRICT_REFLECTIVE_RESOLVE_VALUE =
        getBoolean(FEATURE_STRICT_REFLECTIVE_RESOLVE, false);

    public static boolean FEATURE_CACHE_DAEMON() {
        return FEATURE_CACHE_DAEMON_VALUE;
    }

    /**
     * We can't use stream#flatMap because derived stream evaluates too much.
     * more precisely, it applies #map to all elements generated from element:
     *
     * EXPECTED:
     *       A source:   abc def ghi
     *       B flat:     a b c | d e f | .
     *       C map:      A B C | D . .
     *       d limit(4)  A B C | D
     * UNFORTUNATELY:
     *       A source:   abc def ghi
     *       B flat:     a b c | d e f | .
     *       C map:      A B C | D E F
     *       d limit(4)  A B C | D
     *
     * So we fall-back to our own iterator implementation, sorry
     *
     * Reference:
     *   https://bugs.openjdk.java.net/browse/JDK-8075939
     *   https://stackoverflow.com/questions/29229373/why-filter-after-flatmap-is-not-completely-lazy-in-java-streams
     *
     * @return boolean
     */
    public static boolean FIX_FLAT_STREAM() {
        return FIX_FLAT_STREAM_VALUE;
    }

    public static boolean FIX_FILES_WALKER() {
        return FIX_FILES_WALKER_VALUE;
    }

    public static boolean FEATURE_CASE_SENSITIVE_FILES() {
        return FEATURE_CASE_SENSITIVE_FILES_VALUE;
    }

    public static boolean FEATURE_STRICT_REFLECTIVE_RESOLVE() {
        return FEATURE_STRICT_REFLECTIVE_RESOLVE_VALUE;
    }

    private static Boolean getBoolean(String name, boolean other) {
        return RuntimeUtils.getProperty(name).map(Boolean::parseBoolean).orElse(other);
    }

}
