package lexers

import (
	

	.  // nolint
)

// HTTP lexer.
var HTTP = Register(httpBodyContentTypeLexer(MustNewLexer(
	&Config{
		Name:         "HTTP",
		Aliases:      []string{"http"},
		Filenames:    []string{},
		MimeTypes:    []string{},
		NotMultiline: true,
		DotAll:       true,
	},
	httpRules,
)))

func httpRules() Rules {
	return Rules{
		"root": {
			{`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([123](?:\.[01])?)(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")},
			{`(HTTP)(/)([123](?:\.[01])?)( +)(\d{3})( *)([^\r\n]*)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")},
		},
		"headers": {
			{`([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpHeaderBlock), nil},
			{`([\t ]+)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpContinuousHeaderBlock), nil},
			{`\r?\n`, Text, Push("content")},
		},
		"content": {
			{`.+`, EmitterFunc(httpContentBlock), nil},
		},
	}
}

func httpContentBlock( []string,  *LexerState) Iterator {
	 := []Token{
		{Generic, [0]},
	}
	return Literator(...)
}

func httpHeaderBlock( []string,  *LexerState) Iterator {
	 := []Token{
		{Name, [1]},
		{Text, [2]},
		{Operator, [3]},
		{Text, [4]},
		{Literal, [5]},
		{Text, [6]},
	}
	return Literator(...)
}

func httpContinuousHeaderBlock( []string,  *LexerState) Iterator {
	 := []Token{
		{Text, [1]},
		{Literal, [2]},
		{Text, [3]},
	}
	return Literator(...)
}

func httpBodyContentTypeLexer( Lexer) Lexer { return &httpBodyContentTyper{} }

type httpBodyContentTyper struct{ Lexer }

func ( *httpBodyContentTyper) ( *TokeniseOptions,  string) (Iterator, error) { // nolint: gocognit
	var  string
	var  bool
	var  Iterator

	,  := .Lexer.Tokenise(, )
	if  != nil {
		return nil, 
	}

	return func() Token {
		 := ()

		if  == EOF {
			if  != nil {
				return ()
			}
			return EOF
		}

		switch {
		case .Type == Name && strings.ToLower(.Value) == "content-type":
			{
				 = true
			}
		case .Type == Literal && :
			{
				 = false
				 = strings.TrimSpace(.Value)
				 := strings.Index(, ";")
				if  > 0 {
					 = strings.TrimSpace([:])
				}
			}
		case .Type == Generic &&  != "":
			{
				 := MatchMimeType()

				// application/calendar+xml can be treated as application/xml
				// if there's not a better match.
				if  == nil && strings.Contains(, "+") {
					 := strings.Index(, "/")
					 := strings.LastIndex(, "+")
					 = [:+1] + [+1:]
					 = MatchMimeType()
				}

				if  == nil {
					.Type = Text
				} else {
					,  = .Tokenise(nil, .Value)
					if  != nil {
						panic()
					}
					return EOF
				}
			}
		}
		return 
	}, nil
}