package main

import (
	"fmt"
	"time"
)

// Option adalah fungsi yang mengubah konfigurasi Server.
// Satu Option hanya bertugas mengisi satu bidang konfigurasi.
type Option func(*Server)

// WithTimeout mengembalikan Option yang mengatur batas waktu operasi.
func WithTimeout(d time.Duration) Option {
	return func(s *Server) {
		s.timeout = d
	}
}

// WithMaxConns mengembalikan Option yang mengatur jumlah koneksi maksimum.
func WithMaxConns(n int) Option {
	return func(s *Server) {
		s.maxConns = n
	}
}

// WithName mengembalikan Option yang memberi nama server untuk keperluan log.
func WithName(name string) Option {
	return func(s *Server) {
		s.name = name
	}
}

// Server menyimpan hasil penerapan seluruh opsi.
type Server struct {
	name     string
	timeout  time.Duration
	maxConns int
}

// NewServer membuat Server dengan nilai bawaan, lalu menerapkan
// opsi satu per satu lewat parameter variadic opts.
func NewServer(opts ...Option) *Server {
	s := &Server{
		name:     "default",
		timeout:  5 * time.Second,
		maxConns: 10,
	}
	for _, opt := range opts {
		opt(s)
	}
	return s
}

func main() {
	a := NewServer()
	b := NewServer(WithName("payment"), WithTimeout(2*time.Second))
	c := NewServer(
		WithName("report"),
		WithMaxConns(64),
		WithTimeout(500*time.Millisecond),
	)
	for _, s := range []*Server{a, b, c} {
		fmt.Printf("%-8s timeout=%-8s maxConns=%d\n", s.name, s.timeout, s.maxConns)
	}
}
