package click.kamil.springstatemachineexporter.analysis.index;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Scan-time expansion of interface/abstract method calls to concrete implementation method FQNs.
 */
public final class PolymorphicMethodExpansionIndex {

    private static final PolymorphicMethodExpansionIndex EMPTY =
            new PolymorphicMethodExpansionIndex(Map.of(), 0);

    private final Map<String, Map<String, List<String>>> byOwnerAndMethod;
    private final int entryCount;

    public PolymorphicMethodExpansionIndex(
            Map<String, Map<String, List<String>>> byOwnerAndMethod,
            int entryCount) {
        this.byOwnerAndMethod = Collections.unmodifiableMap(deepCopy(byOwnerAndMethod));
        this.entryCount = entryCount;
    }

    public static PolymorphicMethodExpansionIndex empty() {
        return EMPTY;
    }

    public Optional<List<String>> lookup(String ownerFqn, String methodName) {
        if (ownerFqn == null || methodName == null) {
            return Optional.empty();
        }
        Map<String, List<String>> methods = byOwnerAndMethod.get(ownerFqn);
        if (methods == null) {
            return Optional.empty();
        }
        List<String> expanded = methods.get(methodName);
        if (expanded == null || expanded.isEmpty()) {
            return Optional.empty();
        }
        return Optional.of(expanded);
    }

    public int entryCount() {
        return entryCount;
    }

    private static Map<String, Map<String, List<String>>> deepCopy(
            Map<String, Map<String, List<String>>> source) {
        Map<String, Map<String, List<String>>> copy = new HashMap<>();
        for (Map.Entry<String, Map<String, List<String>>> entry : source.entrySet()) {
            copy.put(entry.getKey(), Map.copyOf(entry.getValue()));
        }
        return copy;
    }
}
