// 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"
	"io"
	"runtime"
	"strings"
	"time"

	"source.monogon.dev/go/logging"
	"source.monogon.dev/osbase/logbuffer"
)

type leveledPublisher struct {
	node  *node
	depth int
}

// LeveledFor returns a LeveledLogger publishing interface for a given DN. An error
// may be returned if the DN is malformed.
func (l *LogTree) LeveledFor(dn DN) (logging.Leveled, error) {
	node, err := l.nodeByDN(dn)
	if err != nil {
		return nil, err
	}
	return &leveledPublisher{
		node:  node,
		depth: 0,
	}, nil
}

func (l *LogTree) RawFor(dn DN) (io.Writer, error) {
	node, err := l.nodeByDN(dn)
	if err != nil {
		return nil, fmt.Errorf("could not retrieve raw logger: %w", err)
	}
	return node.rawLineBuffer, nil
}

// MustLeveledFor returns a LeveledLogger publishing interface for a given DN, or
// panics if the given DN is invalid.
func (l *LogTree) MustLeveledFor(dn DN) logging.Leveled {
	leveled, err := l.LeveledFor(dn)
	if err != nil {
		panic(fmt.Errorf("LeveledFor returned: %w", err))
	}
	return leveled
}

func (l *LogTree) MustRawFor(dn DN) io.Writer {
	raw, err := l.RawFor(dn)
	if err != nil {
		panic(fmt.Errorf("RawFor returned: %w", err))
	}
	return raw
}

// SetVerbosity sets the verbosity for a given DN (non-recursively, ie. for that DN
// only, not its children).
func (l *LogTree) SetVerbosity(dn DN, level logging.VerbosityLevel) error {
	node, err := l.nodeByDN(dn)
	if err != nil {
		return err
	}
	node.verbosity = level
	return nil
}

// logRaw is called by this node's LineBuffer any time a raw log line is completed.
// It will create a new entry, append it to the journal, and notify all pertinent
// subscribers.
func (n *node) logRaw(line *logbuffer.Line) {
	e := &entry{
		origin: n.dn,
		raw:    line,
	}
	n.tree.journal.append(e)
	n.tree.journal.notify(e)
}

// LogExternalLeveled injects a ExternalLeveledPayload into a given
// LeveledLogger. This should only be used by systems which translate external
// data sources into leveled logging - see ExternelLeveledPayload for more
// information.
func LogExternalLeveled(l logging.Leveled, e *ExternalLeveledPayload) error {
	publisher, ok := l.(*leveledPublisher)
	if !ok {
		return fmt.Errorf("the given LeveledLogger is not a *leveledPublisher")
	}
	p := e.sanitize()
	entry := &entry{
		origin:  publisher.node.dn,
		leveled: p,
	}
	publisher.node.tree.journal.append(entry)
	publisher.node.tree.journal.notify(entry)
	return nil
}

// log builds a LeveledPayload and entry for a given message, including all related
// metadata. It will create a new entry append it to the journal, and notify all
// pertinent subscribers.
func (l *leveledPublisher) logLeveled(depth int, severity logging.Severity, msg string) {
	_, file, line, ok := runtime.Caller(2 + depth)
	if !ok {
		file = "???"
		line = 1
	} else {
		slash := strings.LastIndex(file, "/")
		if slash >= 0 {
			file = file[slash+1:]
		}
	}

	// Remove leading/trailing newlines and split.
	messages := strings.Split(strings.Trim(msg, "\n"), "\n")

	p := &LeveledPayload{
		timestamp: time.Now(),
		severity:  severity,
		messages:  messages,
		file:      file,
		line:      line,
	}
	e := &entry{
		origin:  l.node.dn,
		leveled: p,
	}
	l.node.tree.journal.append(e)
	l.node.tree.journal.notify(e)
}

// Info implements the LeveledLogger interface.
func (l *leveledPublisher) Info(args ...interface{}) {
	l.logLeveled(l.depth, logging.INFO, fmt.Sprint(args...))
}

// Infof implements the LeveledLogger interface.
func (l *leveledPublisher) Infof(format string, args ...interface{}) {
	l.logLeveled(l.depth, logging.INFO, fmt.Sprintf(format, args...))
}

// Warning implements the LeveledLogger interface.
func (l *leveledPublisher) Warning(args ...interface{}) {
	l.logLeveled(l.depth, logging.WARNING, fmt.Sprint(args...))
}

// Warningf implements the LeveledLogger interface.
func (l *leveledPublisher) Warningf(format string, args ...interface{}) {
	l.logLeveled(l.depth, logging.WARNING, fmt.Sprintf(format, args...))
}

// Error implements the LeveledLogger interface.
func (l *leveledPublisher) Error(args ...interface{}) {
	l.logLeveled(l.depth, logging.ERROR, fmt.Sprint(args...))
}

// Errorf implements the LeveledLogger interface.
func (l *leveledPublisher) Errorf(format string, args ...interface{}) {
	l.logLeveled(l.depth, logging.ERROR, fmt.Sprintf(format, args...))
}

// Fatal implements the LeveledLogger interface.
func (l *leveledPublisher) Fatal(args ...interface{}) {
	l.logLeveled(l.depth, logging.FATAL, fmt.Sprint(args...))
}

// Fatalf implements the LeveledLogger interface.
func (l *leveledPublisher) Fatalf(format string, args ...interface{}) {
	l.logLeveled(l.depth, logging.FATAL, fmt.Sprintf(format, args...))
}

// WithAddedStackDepth impleemnts the LeveledLogger interface.
func (l *leveledPublisher) WithAddedStackDepth(depth int) logging.Leveled {
	l2 := *l
	l2.depth += depth
	return &l2
}

// V implements the LeveledLogger interface.
func (l *leveledPublisher) V(v logging.VerbosityLevel) logging.VerboseLeveled {
	return &verbose{
		publisher: l,
		enabled:   l.node.verbosity >= v,
	}
}

// verbose implements the VerboseLeveledLogger interface. It is a thin wrapper
// around node, with an 'enabled' bool. This means that V(n)-returned
// VerboseLeveledLoggers must be short lived, as a changed in verbosity will not
// affect all already existing VerboseLeveledLoggers.
type verbose struct {
	publisher *leveledPublisher
	node      *node
	enabled   bool
}

func (v *verbose) Enabled() bool {
	return v.enabled
}

func (v *verbose) Info(args ...interface{}) {
	if !v.enabled {
		return
	}
	v.publisher.logLeveled(v.publisher.depth, logging.INFO, fmt.Sprint(args...))
}

func (v *verbose) Infof(format string, args ...interface{}) {
	if !v.enabled {
		return
	}
	v.publisher.logLeveled(v.publisher.depth, logging.INFO, fmt.Sprintf(format, args...))
}
