// Copyright 2022 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package expectations

import (
	"strings"

	"dawn.googlesource.com/dawn/tools/src/cts/result"
)

const (
	tagHeaderStart = `BEGIN TAG HEADER`
	tagHeaderEnd   = `END TAG HEADER`
)

// Parse parses an expectations file, returning the Content
func Parse(body string) (Content, error) {
	// LineType is an enumerator classifying the 'type' of the line.
	type LineType int
	const (
		comment     LineType = iota // The line starts with the '#'
		expectation                 // The line declares an expectation
		blank                       // The line is blank
	)

	// classifyLine returns the LineType for the given line
	classifyLine := func(line string) LineType {
		line = strings.TrimSpace(line)
		switch {
		case line == "":
			return blank
		case strings.HasPrefix(line, "#"):
			return comment
		default:
			return expectation
		}
	}

	content := Content{} // The output content

	var pending Chunk // The current Chunk being parsed

	// flush completes the current chunk, appending it to 'content'
	flush := func() {
		parseTags(&content.Tags, pending.Comments)
		content.Chunks = append(content.Chunks, pending)
		pending = Chunk{}
	}

	lastLineType := blank                         // The type of the last parsed line
	for i, l := range strings.Split(body, "\n") { // For each line...
		lineIdx := i + 1 // line index
		lineType := classifyLine(l)

		// Compare the new line type to the last.
		// Flush the pending chunk if needed.
		if i > 0 {
			switch {
			case
				lastLineType == blank && lineType != blank,             // blank -> !blank
				lastLineType != blank && lineType == blank,             // !blank -> blank
				lastLineType == expectation && lineType != expectation: // expectation -> comment
				flush()
			}
		}

		lastLineType = lineType

		// Handle blank lines and comments.
		switch lineType {
		case blank:
			continue
		case comment:
			pending.Comments = append(pending.Comments, l)
			continue
		}

		// Below this point, we're dealing with an expectation

		// Split the line by whitespace to form a list of tokens
		type Token struct {
			str        string
			start, end int // line offsets (0-based)
		}
		tokens := []Token{}
		if len(l) > 0 { // Parse the tokens
			inToken, s := false, 0
			for i, c := range l {
				if c == ' ' {
					if inToken {
						tokens = append(tokens, Token{l[s:i], s, i})
						inToken = false
					}
				} else if !inToken {
					s = i
					inToken = true
				}
			}
			if inToken {
				tokens = append(tokens, Token{l[s:], s, len(l)})
			}
		}

		// syntaxErr is a helper for returning a SyntaxError with the current
		// line and column index.
		syntaxErr := func(at Token, msg string) error {
			columnIdx := at.start + 1
			if columnIdx == 1 {
				columnIdx = len(l) + 1
			}
			return Diagnostic{Error, lineIdx, columnIdx, msg}
		}

		// peek returns the next token without consuming it.
		// If there are no more tokens then an empty Token is returned.
		peek := func() Token {
			if len(tokens) > 0 {
				return tokens[0]
			}
			return Token{}
		}

		// next returns the next token, consuming it and incrementing the
		// column index.
		// If there are no more tokens then an empty Token is returned.
		next := func() Token {
			if len(tokens) > 0 {
				tok := tokens[0]
				tokens = tokens[1:]
				return tok
			}
			return Token{}
		}

		match := func(str string) bool {
			if peek().str != str {
				return false
			}
			next()
			return true
		}

		// tags parses a [ tag ] block.
		tags := func(use string) (result.Tags, error) {
			if !match("[") {
				return result.Tags{}, nil
			}
			out := result.NewTags()
			for {
				t := next()
				switch t.str {
				case "]":
					return out, nil
				case "":
					return result.Tags{}, syntaxErr(t, "expected ']' for "+use)
				default:
					out.Add(t.str)
				}
			}
		}

		// Parse the optional bug
		var bug string
		if strings.HasPrefix(peek().str, "crbug.com") {
			bug = next().str
		}

		// Parse the optional test tags
		testTags, err := tags("tags")
		if err != nil {
			return Content{}, err
		}

		// Parse the query
		if t := peek(); t.str == "" || t.str[0] == '#' || t.str[0] == '[' {
			return Content{}, syntaxErr(t, "expected test query")
		}
		query := next().str

		// Parse the expected status
		if t := peek(); !strings.HasPrefix(t.str, "[") {
			return Content{}, syntaxErr(t, "expected status")
		}
		status, err := tags("status")
		if err != nil {
			return Content{}, err
		}

		// Parse any optional trailing comment
		comment := ""
		if t := peek(); strings.HasPrefix(t.str, "#") {
			comment = l[t.start:]
		}

		// Append the expectation to the list.
		pending.Expectations = append(pending.Expectations, Expectation{
			Line:    lineIdx,
			Bug:     bug,
			Tags:    testTags,
			Query:   query,
			Status:  status.List(),
			Comment: comment,
		})
	}

	if lastLineType != blank {
		flush()
	}

	return content, nil
}

// parseTags parses the tag information found between tagHeaderStart and
// tagHeaderEnd comments.
func parseTags(tags *Tags, lines []string) {
	// Flags for whether we're currently parsing a TAG HEADER and whether we're
	// also within a tag-set.
	inTagsHeader, inTagSet := false, false
	tagSet := TagSet{} // The currently parsed tag-set
	for _, line := range lines {
		line = strings.TrimSpace(strings.TrimLeft(strings.TrimSpace(line), "#"))
		if strings.Contains(line, tagHeaderStart) {
			if tags.ByName == nil {
				*tags = Tags{
					ByName: map[string]TagSetAndPriority{},
					Sets:   []TagSet{},
				}
			}
			inTagsHeader = true
			continue
		}
		if strings.Contains(line, tagHeaderEnd) {
			return // Reached the end of the TAG HEADER
		}
		if !inTagsHeader {
			continue // Still looking for a tagHeaderStart
		}

		// Below this point, we're in a TAG HEADER.
		tokens := removeEmpty(strings.Split(line, " "))
		for len(tokens) > 0 {
			if inTagSet {
				// Parsing tags in a tag-set (between the '[' and ']')
				if tokens[0] == "]" {
					// End of the tag-set.
					tags.Sets = append(tags.Sets, tagSet)
					inTagSet = false
					break
				} else {
					// Still inside the tag-set. Consume the tag.
					tag := tokens[0]
					tags.ByName[tag] = TagSetAndPriority{
						Set:      tagSet.Name,
						Priority: len(tagSet.Tags),
					}
					tagSet.Tags.Add(tag)
				}
				tokens = tokens[1:]
			} else {
				// Outside of tag-set. Scan for 'tags: ['
				if len(tokens) > 2 && tokens[0] == "tags:" && tokens[1] == "[" {
					inTagSet = true
					tagSet.Tags = result.NewTags()
					tokens = tokens[2:] // Skip 'tags:' and '['
				} else {
					// Tag set names are on their own line.
					// Remember the content of the line, in case the next line
					// starts a tag-set.
					tagSet.Name = strings.Join(tokens, " ")
					break
				}
			}
		}
	}
}

// removeEmpty returns the list of strings with all empty strings removed.
func removeEmpty(in []string) []string {
	out := make([]string, 0, len(in))
	for _, s := range in {
		if s != "" {
			out = append(out, s)
		}
	}
	return out
}
