package logging

import (
	
	
	
)

// Classification is the type of the log entry's classification name.
type Classification string

// Set of standard classifications that can be used by clients and middleware
const (
	Warn  Classification = "WARN"
	Debug Classification = "DEBUG"
)

// Logger is an interface for logging entries at certain classifications.
type Logger interface {
	// Logf is expected to support the standard fmt package "verbs".
	Logf(classification Classification, format string, v ...interface{})
}

// LoggerFunc is a wrapper around a function to satisfy the Logger interface.
type LoggerFunc func(classification Classification, format string, v ...interface{})

// Logf delegates the logging request to the wrapped function.
func ( LoggerFunc) ( Classification,  string,  ...interface{}) {
	(, , ...)
}

// ContextLogger is an optional interface a Logger implementation may expose that provides
// the ability to create context aware log entries.
type ContextLogger interface {
	WithContext(context.Context) Logger
}

// WithContext will pass the provided context to logger if it implements the ContextLogger interface and return the resulting
// logger. Otherwise the logger will be returned as is. As a special case if a nil logger is provided, a Nop logger will
// be returned to the caller.
func ( context.Context,  Logger) Logger {
	if  == nil {
		return Nop{}
	}

	,  := .(ContextLogger)
	if ! {
		return 
	}

	return .WithContext()
}

// Nop is a Logger implementation that simply does not perform any logging.
type Nop struct{}

// Logf simply returns without performing any action
func ( Nop) (Classification, string, ...interface{}) {
	return
}

// StandardLogger is a Logger implementation that wraps the standard library logger, and delegates logging to it's
// Printf method.
type StandardLogger struct {
	Logger *log.Logger
}

// Logf logs the given classification and message to the underlying logger.
func ( StandardLogger) ( Classification,  string,  ...interface{}) {
	if len() != 0 {
		 = string() + " " + 
	}

	.Logger.Printf(, ...)
}

// NewStandardLogger returns a new StandardLogger
func ( io.Writer) *StandardLogger {
	return &StandardLogger{
		Logger: log.New(, "SDK ", log.LstdFlags),
	}
}