// Author: Sandeep Belgavi. In-memory publication; not a durable checkpoint store.
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

public class SnapshotDemo {
    record State(int version, Map<String, List<String>> observations) {
        State {
            var copy = new HashMap<String, List<String>>();
            observations.forEach((key, value) -> copy.put(key, List.copyOf(value)));
            observations = Map.copyOf(copy); // Elements are immutable Strings.
        }
    }
    public static void main(String[] args) {
        var working = new ArrayList<>(List.of("seed"));
        var initial = new State(1, Map.of("tokens", working));
        var published = new AtomicReference<>(initial);
        var reader = published.get();
        working.add("changed-later");
        if (!reader.observations().get("tokens").equals(List.of("seed")))
            throw new AssertionError("Mutable alias escaped");
        var next = new State(2, Map.of("tokens", working));
        if (!published.compareAndSet(initial, next)) throw new AssertionError("Update lost");
        boolean staleAccepted = published.compareAndSet(initial,
                new State(3, Map.of("tokens", List.of("stale"))));
        if (staleAccepted || reader.version() != 1 || published.get().version() != 2)
            throw new AssertionError("Version publication invariant failed");
        System.out.println("old_snapshot_stable=true current_version=2 stale_writer_rejected=true");
    }
}
