import java.util.ArrayList;
import java.util.List;

public class NotifikasiStok {
    public static void main(String[] args) {
        Toko toko = new Toko();

        // Pelanggan hanya berlangganan ke produk yang mereka minati
        toko.daftar("Buku Java", new PelangganEmail("budi@example.com"));
        toko.daftar("Buku Java", new PelangganSms("Siti", "0812-1111-2222"));
        toko.daftar("Pena", new PelangganEmail("dewi@example.com"));

        toko.stokBerubah("Buku Java", 3); // hanya Budi dan Siti yang menerima
        toko.stokBerubah("Pena", 0);      // hanya Dewi
        toko.stokBerubah("Tas", 5);       // tidak ada pelanggan berlangganan
    }
}

// Observer: antarmuka yang dipanggil subject saat peristiwa terjadi
interface Pelanggan {
    void terima(String produk, int stokBaru);
}

class PelangganEmail implements Pelanggan {
    private final String alamat;

    PelangganEmail(String alamat) {
        this.alamat = alamat;
    }

    @Override
    public void terima(String produk, int stokBaru) {
        System.out.println("  -> email ke " + alamat
                + ": stok \"" + produk + "\" kini " + stokBaru);
    }
}

class PelangganSms implements Pelanggan {
    private final String nama;
    private final String nomor;

    PelangganSms(String nama, String nomor) {
        this.nama = nama;
        this.nomor = nomor;
    }

    @Override
    public void terima(String produk, int stokBaru) {
        System.out.println("  -> sms ke " + nomor + " (" + nama
                + "): stok \"" + produk + "\" kini " + stokBaru);
    }
}

// Subject: menyimpan daftar pendengar dan siarkan peristiwa tanpa mengenal detailnya
class Toko {
    private final List<Langganan> daftarLangganan = new ArrayList<>();

    private record Langganan(String produk, Pelanggan pelanggan) {
    }

    void daftar(String produk, Pelanggan pelanggan) {
        daftarLangganan.add(new Langganan(produk, pelanggan));
    }

    void stokBerubah(String produk, int stokBaru) {
        System.out.println("stok \"" + produk + "\" berubah menjadi " + stokBaru);
        // Urutan pemberitahuan mengikuti urutan pendaftaran: dapat diprediksi
        for (Langganan langganan : daftarLangganan) {
            if (langganan.produk().equals(produk)) {
                langganan.pelanggan().terima(produk, stokBaru);
            }
        }
    }
}
