package config

import (
	"fmt"
	"strings"
)

// StringList represents the "poor man's list" that terraform uses
// internally
type StringList string

// This is the delimiter used to recognize and split StringLists
//
// It plays two semantic roles:
//   * It introduces a list
//   * It terminates each element
//
// Example representations:
// []             => SLD
// [""]           => SLDSLD
// [" "]          => SLD SLD
// ["foo"]        => SLDfooSLD
// ["foo", "bar"] => SLDfooSLDbarSLD
// ["", ""]       => SLDSLDSLD
const stringListDelim = `B780FFEC-B661-4EB8-9236-A01737AD98B6`

// Takes a Stringlist and returns one without empty strings in it
func (sl StringList) Compact() StringList {
	parts := sl.Slice()

	newlist := []string{}
	// drop the empty strings
	for i := range parts {
		if parts[i] != "" {
			newlist = append(newlist, parts[i])
		}
	}
	return NewStringList(newlist)
}

// Build a StringList from a slice
func NewStringList(parts []string) StringList {
	// We have to special case the empty list representation
	if len(parts) == 0 {
		return StringList(stringListDelim)
	}
	return StringList(fmt.Sprintf("%s%s%s",
		stringListDelim,
		strings.Join(parts, stringListDelim),
		stringListDelim,
	))
}

// Returns an element at the index, wrapping around the length of the string
// when index > list length
func (sl StringList) Element(index int) string {
	if sl.Length() == 0 {
		return ""
	}
	return sl.Slice()[index%sl.Length()]
}

// Returns the length of the StringList
func (sl StringList) Length() int {
	return len(sl.Slice())
}

// Returns a slice of strings as represented by this StringList
func (sl StringList) Slice() []string {
	parts := strings.Split(string(sl), stringListDelim)

	// split on an empty StringList will have a length of 2, since there is
	// always at least one deliminator
	if len(parts) <= 2 {
		return []string{}
	}

	// strip empty elements generated by leading and trailing delimiters
	return parts[1 : len(parts)-1]
}

func (sl StringList) String() string {
	return string(sl)
}

// Determines if a given string represents a StringList
func IsStringList(s string) bool {
	return strings.Contains(s, stringListDelim)
}
