package p.studio.compiler.workspaces.stages;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import p.studio.utilities.structures.ReadOnlySet;

import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.Objects;
import java.util.Set;

final class SourceCrawler extends SimpleFileVisitor<Path> {

    private static final Set<String> IGNORED_DIRS = Set.of(
            ".git",
            ".prometeu",
            ".workspace",
            "target",
            "build",
            "out",
            "node_modules"
    );

    private final ReadOnlySet<String> allowedExtensions;
    private final List<Path> paths;

    public SourceCrawler(
            final ReadOnlySet<String> allowedExtensions,
            final List<Path> paths) {
        this.allowedExtensions = allowedExtensions;
        this.paths = paths;
    }

    @Override
    public FileVisitResult preVisitDirectory(final Path path, final BasicFileAttributes attrs) {
        for (final var directory : path) {
            if (!isAllowedPath(directory)) {
                return FileVisitResult.SKIP_SUBTREE;
            }
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(final Path path, final BasicFileAttributes attrs) {
        if (!attrs.isRegularFile()) {
            return FileVisitResult.CONTINUE;
        }

        if (hasAllowedExt(path, allowedExtensions)) {
            paths.add(path);
        }

        return FileVisitResult.CONTINUE;
    }

    private static boolean isAllowedPath(
            final Path path) {
        for (Path part : path) {
            if (IGNORED_DIRS.contains(part.toString())) {
                return false;
            }
        }
        return true;
    }

    private static boolean hasAllowedExt(
            final Path path,
            final ReadOnlySet<String> allowedExtensions) {

        final var fileName = path.getFileName();
        if (Objects.isNull(fileName)) {
            return false;
        }

        final var extension = FilenameUtils.getExtension(fileName.toString()).toLowerCase();
        if (StringUtils.isBlank(extension)) {
            return false;
        }

        return allowedExtensions.contains(extension);
    }
}