package cascadia

import (
	
	
	
)

// implements the reverse operation Sel -> string

var specialCharReplacer *strings.Replacer

func init() {
	var  []string
	for ,  := range ",!\"#$%&'()*+ -./:;<=>?@[\\]^`{|}~" {
		 = append(, string(), "\\"+string())
	}
	specialCharReplacer = strings.NewReplacer(...)
}

// espace special CSS char
func escape( string) string { return specialCharReplacer.Replace() }

func ( tagSelector) () string {
	return .tag
}

func ( idSelector) () string {
	return "#" + escape(.id)
}

func ( classSelector) () string {
	return "." + escape(.class)
}

func ( attrSelector) () string {
	 := .val
	if .operation == "#=" {
		 = .regexp.String()
	} else if .operation != "" {
		 = fmt.Sprintf(`"%s"`, )
	}

	 := ""

	if .insensitive {
		 = " i"
	}

	return fmt.Sprintf(`[%s%s%s%s]`, .key, .operation, , )
}

func ( relativePseudoClassSelector) () string {
	return fmt.Sprintf(":%s(%s)", .name, .match.String())
}

func ( containsPseudoClassSelector) () string {
	 := "contains"
	if .own {
		 += "Own"
	}
	return fmt.Sprintf(`:%s("%s")`, , .value)
}

func ( regexpPseudoClassSelector) () string {
	 := "matches"
	if .own {
		 += "Own"
	}
	return fmt.Sprintf(":%s(%s)", , .regexp.String())
}

func ( nthPseudoClassSelector) () string {
	if .a == 0 && .b == 1 { // special cases
		 := ":first-"
		if .last {
			 = ":last-"
		}
		if .ofType {
			 += "of-type"
		} else {
			 += "child"
		}
		return 
	}
	var  string
	switch [2]bool{.last, .ofType} {
	case [2]bool{true, true}:
		 = "nth-last-of-type"
	case [2]bool{true, false}:
		 = "nth-last-child"
	case [2]bool{false, true}:
		 = "nth-of-type"
	case [2]bool{false, false}:
		 = "nth-child"
	}
	 := fmt.Sprintf("+%d", .b)
	if .b < 0 { // avoid +-8 invalid syntax
		 = strconv.Itoa(.b)
	}
	return fmt.Sprintf(":%s(%dn%s)", , .a, )
}

func ( onlyChildPseudoClassSelector) () string {
	if .ofType {
		return ":only-of-type"
	}
	return ":only-child"
}

func ( inputPseudoClassSelector) () string {
	return ":input"
}

func ( emptyElementPseudoClassSelector) () string {
	return ":empty"
}

func ( rootPseudoClassSelector) () string {
	return ":root"
}

func ( linkPseudoClassSelector) () string {
	return ":link"
}

func ( langPseudoClassSelector) () string {
	return fmt.Sprintf(":lang(%s)", .lang)
}

func ( neverMatchSelector) () string {
	return .value
}

func ( enabledPseudoClassSelector) () string {
	return ":enabled"
}

func ( disabledPseudoClassSelector) () string {
	return ":disabled"
}

func ( checkedPseudoClassSelector) () string {
	return ":checked"
}

func ( compoundSelector) () string {
	if len(.selectors) == 0 && .pseudoElement == "" {
		return "*"
	}
	 := make([]string, len(.selectors))
	for ,  := range .selectors {
		[] = .String()
	}
	 := strings.Join(, "")
	if .pseudoElement != "" {
		 += "::" + .pseudoElement
	}
	return 
}

func ( combinedSelector) () string {
	 := .first.String()
	if .second != nil {
		 += fmt.Sprintf(" %s %s", string(.combinator), .second.String())
	}
	return 
}

func ( SelectorGroup) () string {
	 := make([]string, len())
	for ,  := range  {
		[] = .String()
	}
	return strings.Join(, ", ")
}