/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 *
 * This work is published and licensed under a Creative Commons
 * Attribution-NonCommercial-NoDerivatives 4.0 International License.
 *
 * Distribution of this work is permitted, but commercial use and
 * modifications are strictly prohibited.
 */
package logger

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

var (
	mtx    sync.Mutex
	output io.WriteCloser = os.Stderr
)

type Logger struct {
	subject string
	writer  io.WriteCloser
	mtx     *sync.Mutex
}

func NewLogger(subj string) *Logger {
	return &Logger{
		subject: subj,
		writer:  output,
		mtx:     &mtx,
	}
}

func xxxNewLogger() *Logger {
	return &Logger{
		writer: output,
		mtx:    &mtx,
	}
}

func SetWriter(newOut io.WriteCloser) {
	mtx.Lock()
	output = newOut
	mtx.Unlock()
}

func (logg *Logger) SetWriter(newOut io.WriteCloser) {
	mtx.Lock()
	logg.writer = newOut
	var newMtx sync.Mutex
	logg.mtx = &newMtx
	mtx.Unlock()
}

func (logg *Logger) Debugf(message string, args ...any) {
	logg.printf("debug", message, args...)
}

func (logg *Logger) Infof(message string, args ...any) {
	logg.printf("info", message, args...)
}

func (logg *Logger) Warningf(message string, args ...any) {
	logg.printf("warning", message, args...)
}

func (logg *Logger) Errorf(message string, args ...any) {
	logg.printf("error", message, args...)
}

func (logg *Logger) printf(level, message string, args ...any) {
	timestamp := time.Now().Format(time.RFC3339)
	buffer := bytes.NewBuffer([]byte{})
	if logg.subject != "" {
		fmt.Fprintf(buffer, "%s %s.%s: ", timestamp, logg.subject, level)
	} else {
		fmt.Fprintf(buffer, "%s %s: ", timestamp, level)
	}
	fmt.Fprintf(buffer, message, args...)
	fmt.Fprintf(buffer, "\n")
	logg.mtx.Lock()
	fmt.Fprint(output, buffer.String())
	logg.mtx.Unlock()
}
