package util

import (
	"strings"
	"unicode"
)

// String wraps a string for manipulation
type String struct {
	source string
}

// From creates a String instance
func From(s string) String {
	return String{source: s}
}

// ToCamel converts string to camelCase
func (s String) ToCamel() string {
	if s.source == "" {
		return ""
	}

	words := splitWords(s.source)
	if len(words) == 0 {
		return s.source
	}

	result := strings.Builder{}
	for i, word := range words {
		if i == 0 {
			result.WriteString(strings.ToLower(word))
		} else {
			result.WriteString(title(word))
		}
	}
	return result.String()
}

// Untitle converts first character to lowercase
func (s String) Untitle() string {
	if s.source == "" {
		return ""
	}
	runes := []rune(s.source)
	runes[0] = unicode.ToLower(runes[0])
	return string(runes)
}

// splitWords splits a string into words by common separators
func splitWords(s string) []string {
	var words []string
	var current strings.Builder

	for i, r := range s {
		if r == '_' || r == '-' || r == ' ' || r == '.' {
			if current.Len() > 0 {
				words = append(words, current.String())
				current.Reset()
			}
			continue
		}

		if i > 0 && unicode.IsUpper(r) && !unicode.IsUpper(rune(s[i-1])) {
			if current.Len() > 0 {
				words = append(words, current.String())
				current.Reset()
			}
		}

		current.WriteRune(r)
	}

	if current.Len() > 0 {
		words = append(words, current.String())
	}

	return words
}

// title capitalizes the first character of a string
func title(s string) string {
	if s == "" {
		return ""
	}
	runes := []rune(s)
	runes[0] = unicode.ToUpper(runes[0])
	return string(runes)
}

