package main

import (
	"fmt"
	"os"
)

// Kontrak exit code program. Nilai ini dibaca oleh skrip lain
// atau pipeline yang memanggil kalkulator.
const (
	exitSukses     = 0 // perhitungan berhasil, hasil tercetak ke stdout
	exitPenggunaan = 1 // format perintah salah
	exitSalahInput = 2 // operasi tak dikenal, angka tak valid, atau bagi dengan nol
)

func main() {
	// os.Exit dipanggil di luar jalankan agar defer tetap bekerja
	// bila kelak ditambahkan di dalam jalankan.
	os.Exit(jalankan(os.Args[1:]))
}

// jalankan memproses argumen program dan mengembalikan exit code.
func jalankan(args []string) int {
	if len(args) != 3 {
		fmt.Fprintln(os.Stderr, "Penggunaan: kalkulator <operasi> <angka1> <angka2>")
		fmt.Fprintln(os.Stderr, "Operasi yang tersedia: tambah, kurang, kali, bagi")
		return exitPenggunaan
	}

	a, b, err := ParseInput(args[0], args[1], args[2])
	if err != nil {
		fmt.Fprintln(os.Stderr, "Input tidak valid:", err)
		return exitSalahInput
	}

	hasil, err := hitung(args[0], a, b)
	if err != nil {
		fmt.Fprintln(os.Stderr, "Galat perhitungan:", err)
		return exitSalahInput
	}

	fmt.Printf("Hasil: %g\n", hasil)
	return exitSukses
}

// hitung menjalankan operasi yang diminta terhadap a dan b.
func hitung(operasi string, a, b float64) (float64, error) {
	switch operasi {
	case "tambah":
		return Tambah(a, b), nil
	case "kurang":
		return Kurang(a, b), nil
	case "kali":
		return Kali(a, b), nil
	case "bagi":
		return Bagi(a, b)
	default:
		return 0, fmt.Errorf("operasi %q tidak dikenal", operasi)
	}
}
