package org.implab.gradle.common.core.lang;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Stream;

public final class FilePaths {
    private static PathCollector defaultPathCollector = new PathCollector();

    private FilePaths() {
    }

    public static String cat(String fist, String... extra) {
        return catPath(fist, extra).toString();
    }

    public static Path catPath(String first, String ...extra) {
        return Stream.concat(Stream.of(first), Stream.of(extra))
                .collect(asPath());
    }

    public static Collector<String, List<String>, Path> asPath() {
        return defaultPathCollector;
    }

    static class PathCollector implements Collector<String, List<String>, Path> {

        private final Function<String, String> sanitizer;

        public PathCollector() {
            sanitizer = Strings::sanitizeFileName;
        }

        @Override
        public BiConsumer<List<String>, String> accumulator() {
            return (components, item) -> components.add(sanitizer.apply(item));
        }

        @Override
        public Set<Characteristics> characteristics() {
            return Set.of();
        }

        @Override
        public BinaryOperator<List<String>> combiner() {
            return (first, extra) -> {
                first.addAll(extra);
                return first;
            };
        }

        @Override
        public Function<List<String>, Path> finisher() {
            return components -> Paths.get(
                    components.get(0),
                    components.subList(1, components.size())
                            .toArray(String[]::new));

        }

        @Override
        public Supplier<List<String>> supplier() {
            return () -> new LinkedList<>();
        }

    }
}
