package attributes

import (
	"fmt"
	"strings"

	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
)

const keyValueSeparator = ":"

// ReadNodeAttributes parses node attributes from list of string in "Key:Value" format
// and writes them into netmap.NodeInfo instance. Supports escaped symbols
// "\:", "\/" and "\\".
func ReadNodeAttributes(dst *netmap.NodeInfo, attrs []string) error {
	cache := make(map[string]struct{}, len(attrs))

	for i := range attrs {
		line := replaceEscaping(attrs[i], false) // replaced escaped symbols with non-printable symbols

		k, v, found := strings.Cut(line, keyValueSeparator)
		if !found {
			return fmt.Errorf("wrong format for node attribute: '%s'", attrs[i])
		}

		_, ok := cache[k]
		if ok {
			return fmt.Errorf("duplicated keys %s", k)
		}

		cache[k] = struct{}{}

		// replace non-printable symbols with escaped symbols without escape character
		k = replaceEscaping(k, true)
		v = replaceEscaping(v, true)

		if k == "" {
			return fmt.Errorf("empty key in node attribute: '%s'", attrs[i])
		} else if v == "" {
			return fmt.Errorf("empty value in node attribute: '%s'", attrs[i])
		}

		dst.SetAttribute(k, v)
	}

	return nil
}

func replaceEscaping(target string, rollback bool) (s string) {
	const escChar = `\`

	var (
		oldKVSep = escChar + keyValueSeparator
		oldEsc   = escChar + escChar
		newKVSep = string(uint8(2))
		newEsc   = string(uint8(3))
	)

	if rollback {
		oldKVSep, oldEsc = newKVSep, newEsc
		newKVSep = keyValueSeparator
		newEsc = escChar
	}

	s = strings.ReplaceAll(target, oldEsc, newEsc)
	s = strings.ReplaceAll(s, oldKVSep, newKVSep)

	return
}