package serialize

import (
	"bytes"
	"fmt"

	"github.com/kr/logfmt"
)

type talLogfmt struct {
	Kind       uint64            `logfmt:"K"`
	Time       uint64            `logfmt:"T"`
	Service    string            `logfmt:"S"`
	Machine    string            `logfmt:"M"`
	PID        int               `logfmt:"P"`
	TraceID    uint64            `logfmt:"I"`
	SubTraceID string            `logfmt:"R"`
	Desc       map[string]string `logfmt:"D"`
}

var descLogfmtPrefix = []byte("D.")

func (msg *talLogfmt) HandleLogfmt(key, val []byte) error {
	if bytes.HasPrefix(key, descLogfmtPrefix) {
		k := string(bytes.TrimPrefix(key, descLogfmtPrefix))
		v := string(val)
		if msg.Desc == nil {
			msg.Desc = make(map[string]string)
		}
		msg.Desc[k] = v
	}

	h, err := logfmt.NewStructHandler(msg)
	if err != nil {
		return err
	}
	return h.HandleLogfmt(key, val)
}

func (msg *talLogfmt) MarshalText() ([]byte, error) {
	w := new(bytes.Buffer)
	fmt.Fprintf(w, "K=%d T=%d S=%q M=%q P=%d I=%d R=%q",
		msg.Kind, msg.Time, msg.Service, msg.Machine,
		msg.PID, msg.TraceID, msg.SubTraceID)

	for k, v := range msg.Desc {
		fmt.Fprintf(w, " D.%s=%q", k, v)
	}

	return w.Bytes(), nil
}

func toLogfmt(out *talLogfmt, in *talGolden) error {
	*out = talLogfmt{
		Kind:       uint64(in.Kind),
		Time:       in.Time,
		Service:    in.Service,
		Machine:    in.Machine,
		PID:        in.PID,
		TraceID:    in.TraceID,
		SubTraceID: in.SubTraceID,
	}
	out.Desc = make(map[string]string, len(in.Desc))
	for k, v := range in.Desc {
		out.Desc[k] = v
	}
	return nil
}

func fromLogfmt(out *talGolden, in *talLogfmt) error {
	*out = talGolden{
		Kind:       uint(in.Kind),
		Time:       in.Time,
		Service:    in.Service,
		Machine:    in.Machine,
		PID:        in.PID,
		TraceID:    in.TraceID,
		SubTraceID: in.SubTraceID,
	}
	out.Desc = make(map[string]string, len(in.Desc))
	for k, v := range in.Desc {
		out.Desc[k] = v
	}
	return nil
}
