import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/** Membaca manifest seperti launcher java -jar: Main-Class dan Class-Path relatif. */
public class BacaManifest {

    /** Bangun manifest dari pasangan atribut, lalu serikan ke bytes (format MANIFEST.MF). */
    static byte[] buatManifest(String[][] atribut) throws Exception {
        Manifest mf = new Manifest();
        Attributes utama = mf.getMainAttributes();
        utama.put(Attributes.Name.MANIFEST_VERSION, "1.0");
        for (String[] pasangan : atribut) {
            utama.putValue(pasangan[0], pasangan[1]);
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        mf.write(out);
        return out.toByteArray();
    }

    /** Baca kembali bytes manifest — tahap yang dilakukan launcher sebelum menjalankan JAR. */
    static Manifest bacaManifest(byte[] bytes) throws Exception {
        return new Manifest(new ByteArrayInputStream(bytes));
    }

    /** Selesaikan entry Class-Path relatif terhadap lokasi berkas JAR. */
    static String jalurAbsolut(String direktoriJar, String entryRelatif) {
        return direktoriJar + "/" + entryRelatif;
    }

    public static void main(String[] args) throws Exception {
        byte[] bytes = buatManifest(new String[][]{
                {"Main-Class", "toko.AplikasiKasir"},
                {"Class-Path", "lib/util.jar lib/promo.jar"}
        });

        System.out.println("== Isi MANIFEST.MF hasil serialisasi ==");
        // Spesifikasi JAR mewajibkan CRLF sebagai penanda baris pada manifest;
        // dinormalisasi ke \n agar tampilan output rapi di terminal.
        System.out.print(new String(bytes, StandardCharsets.UTF_8).replace("\r\n", "\n"));

        Manifest terbaca = bacaManifest(bytes);
        Attributes utama = terbaca.getMainAttributes();
        System.out.println("== Interpretasi launcher java -jar ==");
        System.out.println("Main-Class : " + utama.getValue(Attributes.Name.MAIN_CLASS));

        String classPath = utama.getValue(Attributes.Name.CLASS_PATH);
        if (classPath == null) {
            System.out.println("Class-Path : (tidak ada) -> hanya isi JAR sendiri");
        } else {
            System.out.println("Class-Path : " + classPath);
            for (String entry : classPath.split(" ")) {
                System.out.println("  " + entry + " -> " + jalurAbsolut("dist", entry));
            }
        }

        System.out.println("== Manifest tanpa Main-Class ==");
        byte[] tanpaMain = buatManifest(new String[][]{
                {"Class-Path", "lib/util.jar"}
        });
        Manifest m2 = bacaManifest(tanpaMain);
        String main = m2.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
        System.out.println("Main-Class : " + main);
        System.out.println("hasil      : launcher menolak, JAR bukan aplikasi eksekusi");
    }
}
