// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package logtree

import (
	"fmt"

	apb "source.monogon.dev/metropolis/proto/api"
)

// LeveledLogger is a generic interface for glog-style logging. There are four
// hardcoded log severities, in increasing order: INFO, WARNING, ERROR, FATAL.
// Logging at a certain severity level logs not only to consumers expecting data at
// that severity level, but also all lower severity levels. For example, an ERROR
// log will also be passed to consumers looking at INFO or WARNING logs.
type LeveledLogger interface {
	// Info logs at the INFO severity. Arguments are handled in the manner of
	// fmt.Print, a terminating newline is added if missing.
	Info(args ...interface{})
	// Infof logs at the INFO severity. Arguments are handled in the manner of
	// fmt.Printf, a terminating newline is added if missing.
	Infof(format string, args ...interface{})

	// Warning logs at the WARNING severity. Arguments are handled in the manner of
	// fmt.Print, a terminating newline is added if missing.
	Warning(args ...interface{})
	// Warningf logs at the WARNING severity. Arguments are handled in the manner of
	// fmt.Printf, a terminating newline is added if missing.
	Warningf(format string, args ...interface{})

	// Error logs at the ERROR severity. Arguments are handled in the manner of
	// fmt.Print, a terminating newline is added if missing.
	Error(args ...interface{})
	// Errorf logs at the ERROR severity. Arguments are handled in the manner of
	// fmt.Printf, a terminating newline is added if missing.
	Errorf(format string, args ...interface{})

	// Fatal logs at the FATAL severity and aborts the current program. Arguments are
	// handled in the manner of fmt.Print, a terminating newline is added if missing.
	Fatal(args ...interface{})
	// Fatalf logs at the FATAL severity and aborts the current program. Arguments are
	// handled in the manner of fmt.Printf, a terminating newline is added if missing.
	Fatalf(format string, args ...interface{})

	// V returns a VerboseLeveledLogger at a given verbosity level. These verbosity
	// levels can be dynamically set and unset on a package-granular level by consumers
	// of the LeveledLogger logs. The returned value represents whether logging at the
	// given verbosity level was active at that time, and as such should not be a long-
	// lived object in programs. This construct is further refered to as 'V-logs'.
	V(level VerbosityLevel) VerboseLeveledLogger

	// WithAddedStackDepth returns the same LeveledLogger, but adjusted with an
	// additional 'extra stack depth' which will be used to skip a given number of
	// stack/call frames when determining the location where the error originated.
	// For example, WithStackDepth(1) will return a logger that will skip one
	// stack/call frame. Then, with function foo() calling function helper() which
	// in turns call l.Infof(), the log line will be emitted with the call site of
	// helper() within foo(), instead of the default behaviour of logging the
	// call site of Infof() within helper().
	//
	// This is useful for functions which somehow wrap loggers in helper functions,
	// for example to expose a slightly different API.
	WithAddedStackDepth(depth int) LeveledLogger
}

// VerbosityLevel is a verbosity level defined for V-logs. This can be changed
// programmatically per Go package. When logging at a given VerbosityLevel V, the
// current level must be equal or higher to V for the logs to be recorded.
// Conversely, enabling a V-logging at a VerbosityLevel V also enables all logging
// at lower levels [Int32Min .. (V-1)].
type VerbosityLevel int32

type VerboseLeveledLogger interface {
	// Enabled returns if this level was enabled. If not enabled, all logging into this
	// logger will be discarded immediately. Thus, Enabled() can be used to check the
	// verbosity level before performing any logging:
	//    if l.V(3).Enabled() { l.Info("V3 is enabled") }
	// or, in simple cases, the convenience function .Info can be used:
	//    l.V(3).Info("V3 is enabled")
	// The second form is shorter and more convenient, but more expensive, as its
	// arguments are always evaluated.
	Enabled() bool
	// Info is the equivalent of a LeveledLogger's Info call, guarded by whether this
	// VerboseLeveledLogger is enabled.
	Info(args ...interface{})
	// Infof is the equivalent of a LeveledLogger's Infof call, guarded by whether this
	// VerboseLeveledLogger is enabled.
	Infof(format string, args ...interface{})
}

// Severity is one of the severities as described in LeveledLogger.
type Severity string

const (
	INFO    Severity = "I"
	WARNING Severity = "W"
	ERROR   Severity = "E"
	FATAL   Severity = "F"
)

var (
	// SeverityAtLeast maps a given severity to a list of severities that at that
	// severity or higher. In other words, SeverityAtLeast[X] returns a list of
	// severities that might be seen in a log at severity X.
	SeverityAtLeast = map[Severity][]Severity{
		INFO:    {INFO, WARNING, ERROR, FATAL},
		WARNING: {WARNING, ERROR, FATAL},
		ERROR:   {ERROR, FATAL},
		FATAL:   {FATAL},
	}
)

func (s Severity) AtLeast(other Severity) bool {
	for _, el := range SeverityAtLeast[other] {
		if el == s {
			return true
		}
	}
	return false
}

// Valid returns whether true if this severity is one of the known levels
// (INFO, WARNING, ERROR or FATAL), false otherwise.
func (s Severity) Valid() bool {
	switch s {
	case INFO, WARNING, ERROR, FATAL:
		return true
	default:
		return false
	}
}

func SeverityFromProto(s apb.LeveledLogSeverity) (Severity, error) {
	switch s {
	case apb.LeveledLogSeverity_INFO:
		return INFO, nil
	case apb.LeveledLogSeverity_WARNING:
		return WARNING, nil
	case apb.LeveledLogSeverity_ERROR:
		return ERROR, nil
	case apb.LeveledLogSeverity_FATAL:
		return FATAL, nil
	default:
		return "", fmt.Errorf("unknown severity value %d", s)
	}
}

func (s Severity) ToProto() apb.LeveledLogSeverity {
	switch s {
	case INFO:
		return apb.LeveledLogSeverity_INFO
	case WARNING:
		return apb.LeveledLogSeverity_WARNING
	case ERROR:
		return apb.LeveledLogSeverity_ERROR
	case FATAL:
		return apb.LeveledLogSeverity_FATAL
	default:
		return apb.LeveledLogSeverity_INVALID
	}
}
