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

public class LayananDenganInjeksi {
    public static void main(String[] args) {
        System.out.println("== Constructor injection ==");
        LayananPesanan layanan = new LayananPesanan(new PenyimpanMemori());
        layanan.buatPesanan("Budi", 3);
        layanan.buatPesanan("Siti", 1);

        System.out.println("== Method injection ==");
        layanan.lapor(new PemformatBaris());

        System.out.println("== Setter injection ==");
        layanan.ubahPenyimpan(new PenyimpanLog());
        layanan.buatPesanan("Dewi", 2);

        System.out.println("== Fake untuk pengujian ==");
        PenyimpanFake fake = new PenyimpanFake();
        LayananPesanan yangDiuji = new LayananPesanan(fake);
        yangDiuji.buatPesanan("Budi", 5);
        System.out.println("Fake mencatat -> pelanggan: " + fake.terakhirPelanggan
                + ", jumlah: " + fake.terakhirJumlah);
    }
}

interface PenyimpanPesanan {
    long simpan(String pelanggan, int jumlah);

    int jumlahPesanan();
}

class LayananPesanan {
    private PenyimpanPesanan penyimpan;

    LayananPesanan(PenyimpanPesanan penyimpan) {
        this.penyimpan = penyimpan;
    }

    void ubahPenyimpan(PenyimpanPesanan penyimpanBaru) {
        this.penyimpan = penyimpanBaru;
    }

    void buatPesanan(String pelanggan, int jumlah) {
        long id = penyimpan.simpan(pelanggan, jumlah);
        System.out.println("Pesanan #" + id + " untuk " + pelanggan);
    }

    void lapor(Pemformat format) {
        System.out.println(format.tampilkan(penyimpan.jumlahPesanan()));
    }
}

class PenyimpanMemori implements PenyimpanPesanan {
    private final List<String> data = new ArrayList<>();

    public long simpan(String pelanggan, int jumlah) {
        data.add(pelanggan + " x" + jumlah);
        return data.size();
    }

    public int jumlahPesanan() {
        return data.size();
    }
}

class PenyimpanLog implements PenyimpanPesanan {
    private int hitung = 0;

    public long simpan(String pelanggan, int jumlah) {
        hitung++;
        System.out.println("[Log] " + pelanggan + " memesan " + jumlah + " item");
        return 900 + hitung;
    }

    public int jumlahPesanan() {
        return hitung;
    }
}

interface Pemformat {
    String tampilkan(int jumlahPesanan);
}

class PemformatBaris implements Pemformat {
    public String tampilkan(int jumlah) {
        return "Total pesanan tersimpan: " + jumlah;
    }
}

// Fake: merekam panggilan untuk pengujian, tanpa menyimpan apa pun
class PenyimpanFake implements PenyimpanPesanan {
    String terakhirPelanggan;
    int terakhirJumlah;

    public long simpan(String pelanggan, int jumlah) {
        terakhirPelanggan = pelanggan;
        terakhirJumlah = jumlah;
        return 1;
    }

    public int jumlahPesanan() {
        return terakhirPelanggan == null ? 0 : 1;
    }
}
