// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package yaml

import (
	"strings"
)

// DeriveSeqIndentStyle derives the sequence indentation annotation value for the resource,
// originalYAML is the input yaml string,
// the style is decided by deriving the existing sequence indentation of first sequence node
func DeriveSeqIndentStyle(originalYAML string) string {
	lines := strings.Split(originalYAML, "\n")
	for i, line := range lines {
		elems := strings.SplitN(line, "- ", 2)
		if len(elems) != 2 {
			continue
		}
		// prefix of "- " must be sequence of spaces
		if strings.Trim(elems[0], " ") != "" {
			continue
		}
		numSpacesBeforeSeqElem := len(elems[0])

		// keyLine is the line before the first sequence element
		keyLine := keyLineBeforeSeqElem(lines, i)
		if keyLine == "" {
			// there is no keyLine for this sequence node
			// all of those lines are comments
			continue
		}
		numSpacesBeforeKeyElem := len(keyLine) - len(strings.TrimLeft(keyLine, " "))
		trimmedKeyLine := strings.Trim(keyLine, " ")
		if strings.Count(trimmedKeyLine, ":") != 1 || !strings.HasSuffix(trimmedKeyLine, ":") {
			// if the key line doesn't contain only one : that too at the end,
			// this is not a sequence node, it is a wrapped sequence node string
			// ignore it
			continue
		}

		if numSpacesBeforeSeqElem == numSpacesBeforeKeyElem {
			return string(CompactSequenceStyle)
		}

		if numSpacesBeforeSeqElem-numSpacesBeforeKeyElem == 2 {
			return string(WideSequenceStyle)
		}
	}

	return string(CompactSequenceStyle)
}

// keyLineBeforeSeqElem iterates through the lines before the first seqElement
// and tries to find the non-comment key line for the sequence node
func keyLineBeforeSeqElem(lines []string, seqElemIndex int) string {
	// start with the previous line of sequence element
	i := seqElemIndex - 1
	for ; i >= 0; i-- {
		line := lines[i]
		trimmedLine := strings.Trim(line, " ")
		if strings.HasPrefix(trimmedLine, "#") { // commented line
			continue
		}
		// we have a non-commented line which can have a trailing comment
		parts := strings.SplitN(line, "#", 2)
		return parts[0] // throw away the trailing comment part
	}
	return ""
}
