// Copyright 2022 The LUCI Authors.
//
// 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 quotakeys

import (
	"encoding/ascii85"
	"strings"

	"go.chromium.org/luci/common/errors"
)

const (
	// ASIFieldDelim is used to delimit sections within Application Specific
	// Identifiers (ASIs).
	//
	// NOTE: this is ascii85-safe.
	ASIFieldDelim = "|"

	// EncodedSectionPrefix is the prefix used for ASI sections which are nominally
	// encoded with ascii85.
	//
	// NOTE: this is ascii85-safe.
	EncodedSectionPrefix     = "{"
	encodedSectionPrefixRune = '{'

	// EscapedCharacters is the set of characters which are reserved within
	// Application-specific-identifiers (ASIs) and will cause the ASI section to be
	// escaped with ascii85.
	//
	// We also encode ASI sections which start with `EncodedSectionPrefix`.
	EscapedCharacters = QuotaFieldDelim + ASIFieldDelim
)

func extendBuffer(buf []byte, n int) []byte {
	if cap(buf)-len(buf) < n {
		buf = append(make([]byte, 0, len(buf)+n), buf...)
	}
	return buf[:n]
}

// AssembleASI will return an ASI with the given sections.
//
// Sections are assembled with a "|" separator verbatim, unless the section
// contains a "|", "~" or begins with "{". In this case the section will be
// encoded with ascii85 and inserted to the final string with a "{" prefix
// character.
func AssembleASI(sections ...string) string {
	encodedSections := make([]string, len(sections))
	var buf []byte

	for i, section := range sections {
		if strings.HasPrefix(section, EncodedSectionPrefix) || strings.ContainsAny(section, EscapedCharacters) {
			buf = extendBuffer(buf, ascii85.MaxEncodedLen(len(section))+1)
			buf[0] = encodedSectionPrefixRune
			smallBuf := buf[1:]
			encodedSections[i] = string(buf[:ascii85.Encode(smallBuf, []byte(section))+1])
		} else {
			encodedSections[i] = section
		}
	}
	return strings.Join(encodedSections, ASIFieldDelim)
}

// DecodeASI will return the sections within an ASI, decoding any which appear
// to be ascii85-encoded.
//
// If a section has the ascii85 prefix, but doesn't correctly decode, this
// returns an error.
func DecodeASI(asi string) ([]string, error) {
	if asi == "" {
		return nil, nil
	}
	var buf []byte
	sections := strings.Split(asi, ASIFieldDelim)
	for i, section := range sections {
		if strings.HasPrefix(section, EncodedSectionPrefix) {
			buf = extendBuffer(buf, len(section)-1)
			ndst, _, err := ascii85.Decode(buf, []byte(section[1:]), true)
			if err != nil {
				return nil, errors.Annotate(err, "DecodeASI: section[%d]", i).Err()
			}
			sections[i] = string(buf[:ndst])
		}
	}
	return sections, nil
}
