package zsh

import (
	
	
	

	shlex 
	
	
)

var sanitizer = strings.NewReplacer(
	"\n", ``,
	"\r", ``,
	"\t", ``,
)

var quotingReplacer = strings.NewReplacer(
	`'`, `'\''`,
)

var quotingEscapingReplacer = strings.NewReplacer(
	`\`, `\\`,
	`"`, `\"`,
	`$`, `\$`,
	"`", "\\`",
)

var defaultReplacer = strings.NewReplacer(
	`\`, `\\`,
	`&`, `\&`,
	`<`, `\<`,
	`>`, `\>`,
	"`", "\\`",
	`'`, `\'`,
	`"`, `\"`,
	`{`, `\{`,
	`}`, `\}`,
	`$`, `\$`,
	`#`, `\#`,
	`|`, `\|`,
	`?`, `\?`,
	`(`, `\(`,
	`)`, `\)`,
	`;`, `\;`,
	` `, `\ `,
	`[`, `\[`,
	`]`, `\]`,
	`*`, `\*`,
	`~`, `\~`,
)

// additional replacement for use with `_describe` in shell script
var describeReplacer = strings.NewReplacer(
	`\`, `\\`,
	`:`, `\:`,
)

func quoteValue( string) string {
	if strings.HasPrefix(, "~/") || NamedDirectories.Matches() {
		return "~" + defaultReplacer.Replace(strings.TrimPrefix(, "~")) // assume file path expansion
	}
	return defaultReplacer.Replace()
}

type state int

const (
	DEFAULT_STATE state = iota
	// Word starts with `"`.
	// Values need to end with `"` as well.
	// Weirdly regardless whether there are additional quotes within the word.
	QUOTING_ESCAPING_STATE
	// Word starts with `'`.
	// Values need to end with `'` as well.
	// Weirdly regardless whether there are additional quotes within the word.
	QUOTING_STATE
	// Word starts and ends with `"`.
	// Space suffix somehow ends up within the quotes.
	//    `"action"<TAB>`
	//    `"action "<CURSOR>`
	// Workaround for now is to force nospace.
	FULL_QUOTING_ESCAPING_STATE
	// Word starts and ends with `'`.
	// Space suffix somehow ends up within the quotes.
	//    `'action'<TAB>`
	//    `'action '<CURSOR>`
	// Workaround for now is to force nospace.
	FULL_QUOTING_STATE
)

// ActionRawValues formats values for zsh
func ( string,  common.Meta,  common.RawValues) string {
	,  := shlex.Split(env.Compline())
	 := DEFAULT_STATE
	if  == nil {
		 := .CurrentToken().RawValue
		// TODO use token state to determine actual state (might have mixture).
		switch {
		case regexp.MustCompile(`^'$|^'.*[^']$`).MatchString():
			 = QUOTING_STATE
		case regexp.MustCompile(`^"$|^".*[^"]$`).MatchString():
			 = QUOTING_ESCAPING_STATE
		case regexp.MustCompile(`^".*"$`).MatchString():
			 = FULL_QUOTING_ESCAPING_STATE
		case regexp.MustCompile(`^'.*'$`).MatchString():
			 = FULL_QUOTING_STATE
		}
	}

	for ,  := range  {
		switch .Tag {
		case "shorthand flags", "longhand flags":
			[].Tag = "flags" // join to single tag group for classic zsh side-by-side view
		}
	}

	 := make([]string, 0)
	.EachTag(func( string,  common.RawValues) {
		 := make([]string, len())
		 := make([]string, len())
		for ,  := range  {
			 := sanitizer.Replace(.Value)

			switch  {
			case QUOTING_ESCAPING_STATE:
				 = quotingEscapingReplacer.Replace()
				 = describeReplacer.Replace()
				 =  + `"`
			case QUOTING_STATE:
				 = quotingReplacer.Replace()
				 = describeReplacer.Replace()
				 =  + `'`
			case FULL_QUOTING_ESCAPING_STATE:
				 = quotingEscapingReplacer.Replace()
				 = describeReplacer.Replace()
			case FULL_QUOTING_STATE:
				 = quotingReplacer.Replace()
				 = describeReplacer.Replace()
			default:
				 = quoteValue()
				 = describeReplacer.Replace()
			}

			if !.Nospace.Matches(.Value) {
				switch  {
				case FULL_QUOTING_ESCAPING_STATE, FULL_QUOTING_STATE: // nospace workaround
				default:
					 += " "
				}
			}

			 := sanitizer.Replace(.Display)
			 = describeReplacer.Replace() // TODO check if this needs to be applied to description as well
			 := sanitizer.Replace(.Description)

			[] = 

			if strings.TrimSpace() == "" {
				[] = 
			} else {
				[] = fmt.Sprintf("%v:%v", , )
			}
		}
		 = append(, strings.Join([]string{, strings.Join(, "\n"), strings.Join(, "\n")}, "\003"))
	})
	return fmt.Sprintf("%v\001%v\001%v\001", zstyles{}.Format(), message{}.Format(), strings.Join(, "\002")+"\002")
}