package client

import (
	"fmt"
	"os"
	"runtime"

	"github.com/juju/errors"
	"github.com/ngaut/log"
)

var (
	logPrefix = ""
	_log      = log.New()
)

func init() {
	logPrefix = fmt.Sprintf("[case-id: %s] ", os.Getenv(testIDEnv))
	_log = log.Newlogger(os.Stderr, logPrefix)

	_log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	_log.SetHighlighting(runtime.GOOS != "windows")
}

// LogLevel defines type of log level
type LogLevel = log.LogLevel

const (
	// LogLevelNone provides none level logging
	LogLevelNone = log.LOG_LEVEL_NONE
	// LogLevelFatal provides fatal level logging
	LogLevelFatal = log.LOG_LEVEL_FATAL
	// LogLevelError provides error level logging
	LogLevelError = log.LOG_LEVEL_ERROR
	// LogLevelWarn provides warn level logging
	LogLevelWarn = log.LOG_LEVEL_WARN
	// LogLevelInfo provides info level logging
	LogLevelInfo = log.LOG_LEVEL_INFO
	// LogLevelDebug provides debug level logging
	LogLevelDebug = log.LOG_LEVEL_DEBUG
	// LogLevelAll provides all level logging
	LogLevelAll = log.LOG_LEVEL_ALL
)

// SetLogLevel sets the level of builtin logger
func SetLogLevel(lv LogLevel) {
	_log.SetLevel(lv)
}

// Info outputs info level logs
func Info(v ...interface{}) {
	_log.Info(v...)
}

// Infof outputs info level logs
func Infof(format string, v ...interface{}) {
	_log.Infof(format, v...)
}

// Debug outputs debug level logs
func Debug(v ...interface{}) {
	_log.Debug(v...)
}

// Debugf outputs debug level logs
func Debugf(format string, v ...interface{}) {
	_log.Debugf(format, v...)
}

// Warn outputs warn level logs
func Warn(v ...interface{}) {
	_log.Warning(v...)
}

// Warnf outputs warn level logs
func Warnf(format string, v ...interface{}) {
	_log.Warningf(format, v...)
}

// Warning outputs warn level logs
func Warning(v ...interface{}) {
	_log.Warning(v...)
}

// Warningf outputs warn level logs
func Warningf(format string, v ...interface{}) {
	_log.Warningf(format, v...)
}

// Error outputs error level logs
func Error(v ...interface{}) {
	_log.Error(v...)
}

// Errorf outputs error level logs
func Errorf(format string, v ...interface{}) {
	_log.Errorf(format, v...)
}

// Fatal outputs error level logs and exit with -1
func Fatal(v ...interface{}) {
	_log.Fatal(v...)
}

// Fatalf outputs error level logs and exit with -1
func Fatalf(format string, v ...interface{}) {
	_log.Fatalf(format, v...)
}

// NewErrorf wraps errors
func NewErrorf(format string, v ...interface{}) error {
	err := errors.NewErr(logPrefix+format, v...)
	err.SetLocation(1)
	return &err
}

// ErrorStack returns a string representation of the annotated error. If the
// error passed as the parameter is not an annotated error, the result is
// simply the result of the Error() method on that error.
//
// If the error is an annotated error, a multi-line string is returned where
// each line represents one entry in the annotation stack. The full filename
// from the call stack is used in the output.
//
//     first error
//     github.com/juju/errors/annotation_test.go:193:
//     github.com/juju/errors/annotation_test.go:194: annotation
//     github.com/juju/errors/annotation_test.go:195:
//     github.com/juju/errors/annotation_test.go:196: more context
//     github.com/juju/errors/annotation_test.go:197:
func ErrorStack(err error) string {
	return errors.ErrorStack(err)
}
