package main

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

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

	// Bagian 1: buffer bufio.Writer menahan data sampai Flush dipanggil.
	f, err := os.Create(filepath.Join(dir, "log.txt"))
	if err != nil {
		fmt.Println("gagal membuat berkas:", err)
		return
	}
	w := bufio.NewWriter(f)
	fmt.Println("buffer awal        :", w.Available(), "byte")

	if _, err := w.WriteString("halo\n"); err != nil {
		fmt.Println("gagal menulis buffer:", err)
		f.Close()
		return
	}
	fmt.Println("setelah tulis      :", w.Available(), "byte")

	info, err := f.Stat()
	if err != nil {
		fmt.Println("gagal membaca metadata:", err)
		f.Close()
		return
	}
	fmt.Println("disk sebelum Flush :", info.Size(), "byte")

	if err := w.Flush(); err != nil {
		fmt.Println("gagal mengirim buffer:", err)
		f.Close()
		return
	}
	info, err = f.Stat()
	if err != nil {
		fmt.Println("gagal membaca metadata:", err)
		f.Close()
		return
	}
	fmt.Println("disk setelah Flush :", info.Size(), "byte")
	f.Close()

	// Bagian 2: bufio.Reader membaca baris lewat ReadString.
	berkas := filepath.Join(dir, "catatan.txt")
	if err := os.WriteFile(berkas, []byte("senin\nselasa\nrabu\n"), 0644); err != nil {
		fmt.Println("gagal menulis berkas:", err)
		return
	}
	if err := bacaDenganReader(berkas); err != nil {
		fmt.Println("gagal membaca berkas:", err)
	}

	// Bagian 3: Scanner dengan pemisah kata menggantikan pemisah baris.
	teks := strings.NewReader("belajar bufio itu menyenangkan")
	scanner := bufio.NewScanner(teks)
	scanner.Split(bufio.ScanWords)
	kata := 0
	for scanner.Scan() {
		kata++
	}
	if err := scanner.Err(); err != nil {
		fmt.Println("gagal memindai:", err)
		return
	}
	fmt.Println("jumlah kata        :", kata)
}

// bacaDenganReader mencetak setiap baris dengan bufio.Reader.ReadString.
func bacaDenganReader(berkas string) error {
	f, err := os.Open(berkas)
	if err != nil {
		return err
	}
	defer f.Close()

	r := bufio.NewReader(f)
	nomor := 0
	for {
		baris, err := r.ReadString('\n')
		if len(baris) > 0 {
			nomor++
			fmt.Printf("baris %d: %s", nomor, strings.TrimRight(baris, "\n"))
			fmt.Println()
		}
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
	}
}
