// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package slog

import (
	
	
	loginternal 
	
	
	
	
)

var defaultLogger atomic.Pointer[Logger]

var logLoggerLevel LevelVar

// SetLogLoggerLevel controls the level for the bridge to the [log] package.
//
// Before [SetDefault] is called, slog top-level logging functions call the default [log.Logger].
// In that mode, SetLogLoggerLevel sets the minimum level for those calls.
// By default, the minimum level is Info, so calls to [Debug]
// (as well as top-level logging calls at lower levels)
// will not be passed to the log.Logger. After calling
//
//	slog.SetLogLoggerLevel(slog.LevelDebug)
//
// calls to [Debug] will be passed to the log.Logger.
//
// After [SetDefault] is called, calls to the default [log.Logger] are passed to the
// slog default handler. In that mode,
// SetLogLoggerLevel sets the level at which those calls are logged.
// That is, after calling
//
//	slog.SetLogLoggerLevel(slog.LevelDebug)
//
// A call to [log.Printf] will result in output at level [LevelDebug].
//
// SetLogLoggerLevel returns the previous value.
func ( Level) ( Level) {
	 = logLoggerLevel.Level()
	logLoggerLevel.Set()
	return
}

func init() {
	defaultLogger.Store(New(newDefaultHandler(loginternal.DefaultOutput)))
}

// Default returns the default [Logger].
func () *Logger { return defaultLogger.Load() }

// SetDefault makes l the default [Logger], which is used by
// the top-level functions [Info], [Debug] and so on.
// After this call, output from the log package's default Logger
// (as with [log.Print], etc.) will be logged using l's Handler,
// at a level controlled by [SetLogLoggerLevel].
func ( *Logger) {
	defaultLogger.Store()
	// If the default's handler is a defaultHandler, then don't use a handleWriter,
	// or we'll deadlock as they both try to acquire the log default mutex.
	// The defaultHandler will use whatever the log default writer is currently
	// set to, which is correct.
	// This can occur with SetDefault(Default()).
	// See TestSetDefault.
	if ,  := .Handler().(*defaultHandler); ! {
		 := log.Flags()&(log.Lshortfile|log.Llongfile) != 0
		log.SetOutput(&handlerWriter{.Handler(), &logLoggerLevel, })
		log.SetFlags(0) // we want just the log message, no time or location
	}
}

// handlerWriter is an io.Writer that calls a Handler.
// It is used to link the default log.Logger to the default slog.Logger.
type handlerWriter struct {
	h         Handler
	level     Leveler
	capturePC bool
}

func ( *handlerWriter) ( []byte) (int, error) {
	 := .level.Level()
	if !.h.Enabled(context.Background(), ) {
		return 0, nil
	}
	var  uintptr
	if !internal.IgnorePC && .capturePC {
		// skip [runtime.Callers, w.Write, Logger.Output, log.Print]
		var  [1]uintptr
		runtime.Callers(4, [:])
		 = [0]
	}

	// Remove final newline.
	 := len() // Report that the entire buf was written.
	if len() > 0 && [len()-1] == '\n' {
		 = [:len()-1]
	}
	 := NewRecord(time.Now(), , string(), )
	return , .h.Handle(context.Background(), )
}

// A Logger records structured information about each call to its
// Log, Debug, Info, Warn, and Error methods.
// For each call, it creates a [Record] and passes it to a [Handler].
//
// To create a new Logger, call [New] or a Logger method
// that begins "With".
type Logger struct {
	handler Handler // for structured logging
}

func ( *Logger) () *Logger {
	 := *
	return &
}

// Handler returns l's Handler.
func ( *Logger) () Handler { return .handler }

// With returns a Logger that includes the given attributes
// in each output operation. Arguments are converted to
// attributes as if by [Logger.Log].
func ( *Logger) ( ...any) *Logger {
	if len() == 0 {
		return 
	}
	 := .clone()
	.handler = .handler.WithAttrs(argsToAttrSlice())
	return 
}

// WithGroup returns a Logger that starts a group, if name is non-empty.
// The keys of all attributes added to the Logger will be qualified by the given
// name. (How that qualification happens depends on the [Handler.WithGroup]
// method of the Logger's Handler.)
//
// If name is empty, WithGroup returns the receiver.
func ( *Logger) ( string) *Logger {
	if  == "" {
		return 
	}
	 := .clone()
	.handler = .handler.WithGroup()
	return 
}

// New creates a new Logger with the given non-nil Handler.
func ( Handler) *Logger {
	if  == nil {
		panic("nil Handler")
	}
	return &Logger{handler: }
}

// With calls [Logger.With] on the default logger.
func ( ...any) *Logger {
	return Default().With(...)
}

// Enabled reports whether l emits log records at the given context and level.
func ( *Logger) ( context.Context,  Level) bool {
	if  == nil {
		 = context.Background()
	}
	return .Handler().Enabled(, )
}

// NewLogLogger returns a new [log.Logger] such that each call to its Output method
// dispatches a Record to the specified handler. The logger acts as a bridge from
// the older log API to newer structured logging handlers.
func ( Handler,  Level) *log.Logger {
	return log.New(&handlerWriter{, , true}, "", 0)
}

// Log emits a log record with the current time and the given level and message.
// The Record's Attrs consist of the Logger's attributes followed by
// the Attrs specified by args.
//
// The attribute arguments are processed as follows:
//   - If an argument is an Attr, it is used as is.
//   - If an argument is a string and this is not the last argument,
//     the following argument is treated as the value and the two are combined
//     into an Attr.
//   - Otherwise, the argument is treated as a value with key "!BADKEY".
func ( *Logger) ( context.Context,  Level,  string,  ...any) {
	.log(, , , ...)
}

// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs.
func ( *Logger) ( context.Context,  Level,  string,  ...Attr) {
	.logAttrs(, , , ...)
}

// Debug logs at [LevelDebug].
func ( *Logger) ( string,  ...any) {
	.log(context.Background(), LevelDebug, , ...)
}

// DebugContext logs at [LevelDebug] with the given context.
func ( *Logger) ( context.Context,  string,  ...any) {
	.log(, LevelDebug, , ...)
}

// Info logs at [LevelInfo].
func ( *Logger) ( string,  ...any) {
	.log(context.Background(), LevelInfo, , ...)
}

// InfoContext logs at [LevelInfo] with the given context.
func ( *Logger) ( context.Context,  string,  ...any) {
	.log(, LevelInfo, , ...)
}

// Warn logs at [LevelWarn].
func ( *Logger) ( string,  ...any) {
	.log(context.Background(), LevelWarn, , ...)
}

// WarnContext logs at [LevelWarn] with the given context.
func ( *Logger) ( context.Context,  string,  ...any) {
	.log(, LevelWarn, , ...)
}

// Error logs at [LevelError].
func ( *Logger) ( string,  ...any) {
	.log(context.Background(), LevelError, , ...)
}

// ErrorContext logs at [LevelError] with the given context.
func ( *Logger) ( context.Context,  string,  ...any) {
	.log(, LevelError, , ...)
}

// log is the low-level logging method for methods that take ...any.
// It must always be called directly by an exported logging method
// or function, because it uses a fixed call depth to obtain the pc.
func ( *Logger) ( context.Context,  Level,  string,  ...any) {
	if !.Enabled(, ) {
		return
	}
	var  uintptr
	if !internal.IgnorePC {
		var  [1]uintptr
		// skip [runtime.Callers, this function, this function's caller]
		runtime.Callers(3, [:])
		 = [0]
	}
	 := NewRecord(time.Now(), , , )
	.Add(...)
	if  == nil {
		 = context.Background()
	}
	_ = .Handler().Handle(, )
}

// logAttrs is like [Logger.log], but for methods that take ...Attr.
func ( *Logger) ( context.Context,  Level,  string,  ...Attr) {
	if !.Enabled(, ) {
		return
	}
	var  uintptr
	if !internal.IgnorePC {
		var  [1]uintptr
		// skip [runtime.Callers, this function, this function's caller]
		runtime.Callers(3, [:])
		 = [0]
	}
	 := NewRecord(time.Now(), , , )
	.AddAttrs(...)
	if  == nil {
		 = context.Background()
	}
	_ = .Handler().Handle(, )
}

// Debug calls [Logger.Debug] on the default logger.
func ( string,  ...any) {
	Default().log(context.Background(), LevelDebug, , ...)
}

// DebugContext calls [Logger.DebugContext] on the default logger.
func ( context.Context,  string,  ...any) {
	Default().log(, LevelDebug, , ...)
}

// Info calls [Logger.Info] on the default logger.
func ( string,  ...any) {
	Default().log(context.Background(), LevelInfo, , ...)
}

// InfoContext calls [Logger.InfoContext] on the default logger.
func ( context.Context,  string,  ...any) {
	Default().log(, LevelInfo, , ...)
}

// Warn calls [Logger.Warn] on the default logger.
func ( string,  ...any) {
	Default().log(context.Background(), LevelWarn, , ...)
}

// WarnContext calls [Logger.WarnContext] on the default logger.
func ( context.Context,  string,  ...any) {
	Default().log(, LevelWarn, , ...)
}

// Error calls [Logger.Error] on the default logger.
func ( string,  ...any) {
	Default().log(context.Background(), LevelError, , ...)
}

// ErrorContext calls [Logger.ErrorContext] on the default logger.
func ( context.Context,  string,  ...any) {
	Default().log(, LevelError, , ...)
}

// Log calls [Logger.Log] on the default logger.
func ( context.Context,  Level,  string,  ...any) {
	Default().log(, , , ...)
}

// LogAttrs calls [Logger.LogAttrs] on the default logger.
func ( context.Context,  Level,  string,  ...Attr) {
	Default().logAttrs(, , , ...)
}