import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/** Service registry dengan heartbeat dan penemuan sisi klien (round-robin). */
public class RegistryLayanan {

    /** Satu instansi terdaftar: alamat + tick terakhir kali terlihat hidup. */
    static class Instansi {
        final String alamat;
        int terakhirHidup;

        Instansi(String alamat, int tick) {
            this.alamat = alamat;
            this.terakhirHidup = tick;
        }
    }

    /** Registry: menerima pendaftaran dan detak jantung, mengeluarkan instansi yang diam. */
    static class Registry {
        private final int batasDiam;
        private final Map<String, Instansi> tabel = new LinkedHashMap<>();
        private int tick = 0;

        Registry(int batasDiam) {
            this.batasDiam = batasDiam;
        }

        void daftar(String alamat) {
            tabel.put(alamat, new Instansi(alamat, tick));
        }

        void detak(String alamat) {
            Instansi i = tabel.get(alamat);
            if (i != null) {
                i.terakhirHidup = tick;
            }
        }

        /** Satu satuan waktu berlalu; keluarkan instansi yang diam melampaui batas. */
        void tick() {
            tick++;
            Iterator<Instansi> it = tabel.values().iterator();
            while (it.hasNext()) {
                Instansi i = it.next();
                if (tick - i.terakhirHidup > batasDiam) {
                    System.out.println("  [tick " + tick + "] " + i.alamat
                            + " dikeluarkan: diam " + (tick - i.terakhirHidup)
                            + " tick, batas " + batasDiam);
                    it.remove();
                }
            }
        }

        /** Daftar alamat instansi yang masih dianggap sehat, urut pendaftaran. */
        List<String> alamatSehat() {
            List<String> hasil = new ArrayList<>();
            for (Instansi i : tabel.values()) {
                hasil.add(i.alamat);
            }
            return hasil;
        }
    }

    public static void main(String[] args) {
        Registry registry = new Registry(2); // boleh diam paling banyak 2 tick

        System.out.println("== Tiga replika svc-pembayaran terdaftar ==");
        registry.daftar("10.0.1.1:8081");
        registry.daftar("10.0.1.2:8081");
        registry.daftar("10.0.1.3:8081");
        System.out.println("  sehat: " + registry.alamatSehat());

        System.out.println();
        System.out.println("== Simulasi: 10.0.1.3 berhenti mengirim detak jantung ==");
        for (int t = 1; t <= 3; t++) {
            registry.detak("10.0.1.1:8081");
            registry.detak("10.0.1.2:8081");
            registry.tick();
            System.out.println("  setelah tick " + t + " -> sehat: " + registry.alamatSehat());
        }

        System.out.println();
        System.out.println("== Penemuan sisi klien: round-robin di antara yang sehat ==");
        List<String> sehat = registry.alamatSehat();
        for (int panggilan = 1; panggilan <= 4; panggilan++) {
            String alamat = sehat.get((panggilan - 1) % sehat.size());
            System.out.println("  panggilan " + panggilan + " -> " + alamat);
        }
    }
}
