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

	tpb "google.golang.org/protobuf/types/known/timestamppb"

	"source.monogon.dev/go/logging"
	lpb "source.monogon.dev/osbase/logtree/proto"
)

// LeveledPayload is a log entry for leveled logs (as per leveled.go). It contains
// the input to these calls (severity and message split into newline-delimited
// messages) and additional metadata that would be usually seen in a text
// representation of a leveled log entry.
type LeveledPayload struct {
	// messages is the list of messages contained in this payload. This list is built
	// from splitting up the given message from the user by newline.
	messages []string
	// timestamp is the time at which this message was emitted.
	timestamp time.Time
	// severity is the leveled Severity at which this message was emitted.
	severity logging.Severity
	// file is the filename of the caller that emitted this message.
	file string
	// line is the line number within the file of the caller that emitted this message.
	line int
}

// String returns a canonical representation of this payload as a single string
// prefixed with metadata. If the original message was logged with newlines, this
// representation will also contain newlines, with each original message part
// prefixed by the metadata. For an alternative call that will instead return a
// canonical prefix and a list of lines in the message, see Strings().
func (p *LeveledPayload) String() string {
	prefix, lines := p.Strings()
	res := make([]string, len(p.messages))
	for i, line := range lines {
		res[i] = fmt.Sprintf("%s%s", prefix, line)
	}
	return strings.Join(res, "\n")
}

// Strings returns the canonical representation of this payload split into a
// prefix and all lines that were contained in the original message. This is
// meant to be displayed to the user by showing the prefix before each line,
// concatenated together - possibly in a table form with the prefixes all
// unified with a rowspan- like mechanism.
//
// For example, this function can return:
//
//	prefix = "I1102 17:20:06.921395 foo.go:42] "
//	lines = []string{"current tags:", " - one", " - two"}
//
// With this data, the result should be presented to users this way in text form:
// I1102 17:20:06.921395 foo.go:42] current tags:
// I1102 17:20:06.921395 foo.go:42]  - one
// I1102 17:20:06.921395 foo.go:42]  - two
//
// Or, in a table layout:
// .-----------------------------------------------------------.
// | I1102 17:20:06.921395     0 foo.go:42] : current tags:    |
// |                                        :------------------|
// |                                        :  - one           |
// |                                        :------------------|
// |                                        :  - two           |
// '-----------------------------------------------------------'
func (p *LeveledPayload) Strings() (prefix string, lines []string) {
	_, month, day := p.timestamp.Date()
	hour, minute, second := p.timestamp.Clock()
	nsec := p.timestamp.Nanosecond() / 1000

	// Same format as in glog, but without treadid.
	// Lmmdd hh:mm:ss.uuuuuu file:line]
	// TODO(q3k): rewrite this to printf-less code.
	prefix = fmt.Sprintf("%s%02d%02d %02d:%02d:%02d.%06d %s:%d] ", p.severity, month, day, hour, minute, second, nsec, p.file, p.line)

	lines = p.messages
	return
}

// Messages returns the inner message lines of this entry, ie. what was passed
// to the actual logging method, but split by newlines.
func (p *LeveledPayload) Messages() []string { return p.messages }

func (p *LeveledPayload) MessagesJoined() string { return strings.Join(p.messages, "\n") }

// Timestamp returns the time at which this entry was logged.
func (p *LeveledPayload) Timestamp() time.Time { return p.timestamp }

// Location returns a string in the form of file_name:line_number that shows the
// origin of the log entry in the program source.
func (p *LeveledPayload) Location() string { return fmt.Sprintf("%s:%d", p.file, p.line) }

// Severity returns the Severity with which this entry was logged.
func (p *LeveledPayload) Severity() logging.Severity { return p.severity }

// Proto converts a LeveledPayload to protobuf format.
func (p *LeveledPayload) Proto() *lpb.LogEntry_Leveled {
	return &lpb.LogEntry_Leveled{
		Lines:     p.Messages(),
		Timestamp: tpb.New(p.Timestamp()),
		Severity:  SeverityToProto(p.Severity()),
		Location:  p.Location(),
	}
}

// LeveledPayloadFromProto parses a protobuf message into the internal format.
func LeveledPayloadFromProto(p *lpb.LogEntry_Leveled) (*LeveledPayload, error) {
	severity, err := SeverityFromProto(p.Severity)
	if err != nil {
		return nil, fmt.Errorf("could not convert severity: %w", err)
	}
	parts := strings.Split(p.Location, ":")
	if len(parts) != 2 {
		return nil, fmt.Errorf("invalid location, must be two :-delimited parts, is %d parts", len(parts))
	}
	file := parts[0]
	line, err := strconv.Atoi(parts[1])
	if err != nil {
		return nil, fmt.Errorf("invalid location line number: %w", err)
	}
	return &LeveledPayload{
		messages:  p.Lines,
		timestamp: p.Timestamp.AsTime(),
		severity:  severity,
		file:      file,
		line:      line,
	}, nil
}

// ExternalLeveledPayload is a LeveledPayload received from an external source,
// eg. from parsing the logging output of third-party programs. It can be
// converted into a LeveledPayload and inserted into a leveled logger, but will
// be sanitized before that, ensuring that potentially buggy
// emitters/converters do not end up polluting the leveled logger data.
//
// This type should be used only when inserting data from external systems, not
// by code that just wishes to log things. In the future, data inserted this
// way might be explicitly marked as tainted so operators can understand that
// parts of this data might not give the same guarantees as the log entries
// emitted by the native LeveledLogger API.
type ExternalLeveledPayload struct {
	// Log line. If any newlines are found, they will split the message into
	// multiple messages within LeveledPayload. Empty messages are accepted
	// verbatim.
	Message string
	// Timestamp when this payload was emitted according to its source. If not
	// given, will default to the time of conversion to LeveledPayload.
	Timestamp time.Time
	// Log severity. If invalid or unset will default to INFO.
	Severity logging.Severity
	// File name of originating code. Defaults to "unknown" if not set.
	File string
	// Line in File. Zero indicates the line is not known.
	Line int
}

// sanitize the given ExternalLeveledPayload by creating a corresponding
// LeveledPayload. The original object is unaltered.
func (e *ExternalLeveledPayload) sanitize() *LeveledPayload {
	l := &LeveledPayload{
		messages:  strings.Split(e.Message, "\n"),
		timestamp: e.Timestamp,
		severity:  e.Severity,
		file:      e.File,
		line:      e.Line,
	}
	if l.timestamp.IsZero() {
		l.timestamp = time.Now()
	}
	if !l.severity.Valid() {
		l.severity = logging.INFO
	}
	if l.file == "" {
		l.file = "unknown"
	}
	if l.line < 0 {
		l.line = 0
	}
	return l
}
