// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package slog

import (
	"encoding"
	"fmt"
	"io"
	"strconv"
	"strings"
	"time"
	"unicode"

	"golang.org/x/exp/slog/internal/buffer"
)

// TextHandler is a Handler that writes Records to an io.Writer as a
// sequence of key=value pairs separated by spaces and followed by a newline.
type TextHandler struct {
	*commonHandler
}

// NewTextHandler creates a TextHandler that writes to w,
// using the default options.
func NewTextHandler(w io.Writer) *TextHandler {
	return (HandlerOptions{}).NewTextHandler(w)
}

// NewTextHandler creates a TextHandler with the given options that writes to w.
func (opts HandlerOptions) NewTextHandler(w io.Writer) *TextHandler {
	return &TextHandler{
		&commonHandler{
			newAppender: func(buf *buffer.Buffer) appender { return (*textAppender)(buf) },
			w:           w,
			opts:        opts,
		},
	}
}

// With returns a new TextHandler whose attributes consists
// of h's attributes followed by attrs.
func (h *TextHandler) With(attrs []Attr) Handler {
	return &TextHandler{commonHandler: h.commonHandler.with(attrs)}
}

// Handle formats its argument Record as a single line of space-separated
// key=value items.
//
// If the Record's time is zero, the time is omitted.
// Otherwise, the key is "time"
// and the value is output in RFC3339 format with millisecond precision.
//
// If the Record's level is zero, the level is omitted.
// Otherwise, the key is "level"
// and the value of [Level.String] is output.
//
// If the AddSource option is set and source information is available,
// the key is "source" and the value is output as FILE:LINE.
//
// The message's key "msg".
//
// To modify these or other attributes, or remove them from the output, use
// [HandlerOptions.ReplaceAttr].
//
// If a value implements [encoding.TextMarshaler], the result of MarshalText is
// written. Otherwise, the result of fmt.Sprint is written.
//
// Keys and values are quoted if they are long or contain Unicode space
// characters, '"' or '='.
//
// Each call to Handle results in a single serialized call to
// io.Writer.Write.
func (h *TextHandler) Handle(r Record) error {
	return h.commonHandler.handle(r)
}

type textAppender buffer.Buffer

func (a *textAppender) buf() *buffer.Buffer { return (*buffer.Buffer)(a) }

func (a *textAppender) appendKey(key string) {
	a.appendString(key)
	a.buf().WriteByte('=')
}

func (a *textAppender) appendString(s string) {
	if needsQuoting(s) {
		*a.buf() = strconv.AppendQuote(*a.buf(), s)
	} else {
		a.buf().WriteString(s)
	}
}

func needsQuoting(s string) bool {
	return len(s) > maxCheckQuoteSize ||
		strings.IndexFunc(s, func(r rune) bool {
			return unicode.IsSpace(r) || r == '"' || r == '='
		}) >= 0
}

func (a *textAppender) appendStart() {}
func (a *textAppender) appendEnd()   {}
func (a *textAppender) appendSep()   { a.buf().WriteByte(' ') }

const maxCheckQuoteSize = 80

func (a *textAppender) appendTime(t time.Time) {
	*a.buf() = appendTimeRFC3339Millis(*a.buf(), t)
}

func (a *textAppender) appendSource(file string, line int) {
	a.appendString(file)
	a.buf().WriteByte(':')
	itoa((*[]byte)(a.buf()), line, -1)
}

func (ap *textAppender) appendAttrValue(a Attr) error {
	switch a.Kind() {
	case StringKind:
		ap.appendString(a.str())
		return nil
	case TimeKind:
		ap.appendTime(a.Time())
	case AnyKind:
		if tm, ok := a.any.(encoding.TextMarshaler); ok {
			data, err := tm.MarshalText()
			if err != nil {
				ap.appendString("!ERROR:" + err.Error())
			} else {
				// TODO: avoid the conversion to string.
				ap.appendString(string(data))
			}
			return nil
		}
		ap.appendString(fmt.Sprint(a.Value()))
	default:
		*ap.buf() = a.AppendValue(*ap.buf())
	}
	return nil
}
