package p.studio.registry.utilities;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import p.studio.registry.models.ProjectRef;
import p.studio.registry.models.Registry;

import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public final class RegistryStore {
    public static final RegistryStore INSTANCE = new RegistryStore();

    private final static ObjectMapper mapper = new ObjectMapper();

    public Optional<Registry> load(final Path projectRootPathCanon) {
        final var registryPath = projectRootPathCanon
                .resolve(".workspace/repos/registry.json");

        final Map<String, String> map;
        {
            final var file = registryPath.toFile();
            if (!file.exists() || !file.isFile()) {
                return Optional.empty();
            }
            try {
                map = mapper.readValue(file, new TypeReference<>() {});
            } catch (Exception e) {
                return Optional.empty();
            }
        }

        final Map<ProjectRef, Path> repos = new HashMap<>();
        for (final var entry : map.entrySet()) {
            final var pathCanon = canonicalize(projectRootPathCanon, entry.getValue());
            if (pathCanon.isEmpty()) {
                continue;
            }
            ProjectRef.parse(entry.getKey()).ifPresent(ref -> repos.put(ref, pathCanon.get()));
        }

        if (map.size() != repos.size()) {
            return Optional.empty(); // mal formatted registry file
        }

        return Optional.of(new Registry(repos));
    }

    private static Optional<Path> canonicalize(
            final Path projectRootPathCanon,
            final String value) {
        try {
            final var pathResolve = projectRootPathCanon.resolve(value);
            return Optional.of(pathResolve.toRealPath());
        } catch (IOException e) {
            return Optional.empty();
        }
    }
}
