package layoutauthoringv1

import (
	"io"
	"reflect"
)

// Semantic sizes use the same deterministic structural grammar as canonical
// identity, without the digest domain. The count includes presence/type tags,
// semantic field names, string lengths, collection lengths, scalar values and
// every structural node. It is independent of JSON whitespace or protobuf
// implementation details.

// A nonempty field identifier uses a string tag, a length varint, and at
// least one identifier byte in the existing semantic encoding. Longer names
// and all enclosing structure consume the same response budget as usual.
const minimumCreateRequiredFieldSemanticBytes = 3

func LayoutDocumentSemanticSize(document LayoutDocument) int {
	return semanticSize(document)
}

func SemanticRequestSize(request SubmitRequest) int {
	return semanticSize(request)
}

func SemanticResponseSize(response any) int {
	return semanticSize(response)
}

func semanticSize(value any) int {
	counter := &countingWriter{}
	encoder := semanticEncoder{writer: counter}
	if err := encoder.writeValue(reflect.ValueOf(value), 0); err != nil {
		return int(^uint(0) >> 1)
	}
	return counter.count
}

type countingWriter struct{ count int }

func (writer *countingWriter) Write(payload []byte) (int, error) {
	writer.count += len(payload)
	return len(payload), nil
}

var _ io.Writer = (*countingWriter)(nil)
