package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	// Direktori kerja sementara agar program aman dijalankan berulang.
	dir, err := os.MkdirTemp("", "contoh-tulis-*")
	if err != nil {
		fmt.Println("gagal membuat direktori:", err)
		return
	}
	defer os.RemoveAll(dir)

	// Pola 1: os.WriteFile menulis seluruh isi sekaligus dengan permission 0644.
	berkas := filepath.Join(dir, "daftar.txt")
	if err := os.WriteFile(berkas, []byte("nasi goreng\nmie ayam\n"), 0644); err != nil {
		fmt.Println("gagal menulis berkas:", err)
		return
	}
	tampilkan(berkas, "os.WriteFile")

	// Pola 2: os.Create membuat berkas baru atau memotong yang sudah ada.
	f, err := os.Create(berkas)
	if err != nil {
		fmt.Println("gagal membuat berkas:", err)
		return
	}
	if _, err := f.WriteString("nasi goreng\nmie ayam\nsate ayam\n"); err != nil {
		fmt.Println("gagal menulis:", err)
		f.Close()
		return
	}
	if err := f.Close(); err != nil {
		fmt.Println("gagal menutup berkas:", err)
		return
	}
	tampilkan(berkas, "os.Create")

	// Pola 3: os.OpenFile dengan flag append menambah tanpa memotong isi lama.
	fa, err := os.OpenFile(berkas, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("gagal membuka berkas:", err)
		return
	}
	if _, err := fa.WriteString("es teh\n"); err != nil {
		fmt.Println("gagal menulis:", err)
		fa.Close()
		return
	}
	if err := fa.Close(); err != nil {
		fmt.Println("gagal menutup berkas:", err)
		return
	}
	tampilkan(berkas, "append")

	// Pola 4: bufio.Writer menampung tulisan di buffer lalu mengirimnya sekaligus.
	fw, err := os.Create(filepath.Join(dir, "log.txt"))
	if err != nil {
		fmt.Println("gagal membuat berkas:", err)
		return
	}
	w := bufio.NewWriter(fw)
	for _, kata := range []string{"satu", "dua", "tiga"} {
		if _, err := w.WriteString(kata + "\n"); err != nil {
			fmt.Println("gagal menulis buffer:", err)
			fw.Close()
			return
		}
	}
	if err := w.Flush(); err != nil {
		fmt.Println("gagal mengirim buffer:", err)
		fw.Close()
		return
	}
	if err := fw.Close(); err != nil {
		fmt.Println("gagal menutup berkas:", err)
		return
	}
	tampilkan(filepath.Join(dir, "log.txt"), "bufio.Writer")
}

// tampilkan mencetak ukuran dan isi berkas tanpa mencetak path-nya.
func tampilkan(berkas, label string) {
	data, err := os.ReadFile(berkas)
	if err != nil {
		fmt.Println("gagal membaca berkas:", err)
		return
	}
	fmt.Printf("%s: %d byte\n", label, len(data))
	fmt.Print(string(data))
}
