// Copyright 2021 The Tint 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 parser provides a basic parser for the Tint builtin definition
// language
package parser

import (
	"fmt"

	"dawn.googlesource.com/tint/tools/src/cmd/builtin-gen/ast"
	"dawn.googlesource.com/tint/tools/src/cmd/builtin-gen/lexer"
	"dawn.googlesource.com/tint/tools/src/cmd/builtin-gen/tok"
)

// Parse produces a list of tokens for the given source code
func Parse(source, filepath string) (*ast.AST, error) {
	runes := []rune(source)
	tokens, err := lexer.Lex(runes, filepath)
	if err != nil {
		return nil, err
	}

	p := parser{tokens: tokens}
	return p.parse()
}

type parser struct {
	tokens []tok.Token
	err    error
}

func (p *parser) parse() (*ast.AST, error) {
	out := ast.AST{}
	var decorations ast.Decorations
	for p.err == nil {
		t := p.peek(0)
		if t == nil {
			break
		}
		switch t.Kind {
		case tok.Ldeco:
			decorations = append(decorations, p.decorations()...)
		case tok.Enum:
			if len(decorations) > 0 {
				p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source)
			}
			out.Enums = append(out.Enums, p.enumDecl())
		case tok.Match:
			if len(decorations) > 0 {
				p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source)
			}
			out.Matchers = append(out.Matchers, p.matcherDecl())
		case tok.Type:
			out.Types = append(out.Types, p.typeDecl(decorations))
			decorations = nil
		case tok.Function:
			out.Functions = append(out.Functions, p.functionDecl(decorations))
			decorations = nil
		default:
			p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind)
		}
		if p.err != nil {
			return nil, p.err
		}
	}
	return &out, nil
}

func (p *parser) enumDecl() ast.EnumDecl {
	p.expect(tok.Enum, "enum declaration")
	name := p.expect(tok.Identifier, "enum name")
	e := ast.EnumDecl{Source: name.Source, Name: string(name.Runes)}
	p.expect(tok.Lbrace, "enum declaration")
	for p.err == nil && p.match(tok.Rbrace) == nil {
		e.Entries = append(e.Entries, p.enumEntry())
	}
	return e
}

func (p *parser) enumEntry() ast.EnumEntry {
	decos := p.decorations()
	name := p.expect(tok.Identifier, "enum entry")
	return ast.EnumEntry{Source: name.Source, Decorations: decos, Name: string(name.Runes)}
}

func (p *parser) matcherDecl() ast.MatcherDecl {
	p.expect(tok.Match, "matcher declaration")
	name := p.expect(tok.Identifier, "matcher name")
	m := ast.MatcherDecl{Source: name.Source, Name: string(name.Runes)}
	p.expect(tok.Colon, "matcher declaration")
	for p.err == nil {
		m.Options = append(m.Options, p.templatedName())
		if p.match(tok.Or) == nil {
			break
		}
	}
	return m
}

func (p *parser) typeDecl(decos ast.Decorations) ast.TypeDecl {
	p.expect(tok.Type, "type declaration")
	name := p.expect(tok.Identifier, "type name")
	m := ast.TypeDecl{
		Source:      name.Source,
		Decorations: decos,
		Name:        string(name.Runes),
	}
	if p.peekIs(0, tok.Lt) {
		m.TemplateParams = p.templateParams()
	}
	return m
}

func (p *parser) decorations() ast.Decorations {
	if p.match(tok.Ldeco) == nil {
		return nil
	}
	out := ast.Decorations{}
	for p.err == nil {
		name := p.expect(tok.Identifier, "decoration name")
		values := []string{}
		if p.match(tok.Lparen) != nil {
			for p.err == nil {
				values = append(values, p.string())
				if p.match(tok.Comma) == nil {
					break
				}
			}
			p.expect(tok.Rparen, "decoration values")
		}
		out = append(out, ast.Decoration{
			Source: name.Source,
			Name:   string(name.Runes),
			Values: values,
		})
		if !p.peekIs(0, tok.Comma) {
			break
		}
	}
	p.expect(tok.Rdeco, "decoration list")
	return out
}

func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl {
	p.expect(tok.Function, "function declaration")
	name := p.expect(tok.Identifier, "function name")
	f := ast.FunctionDecl{
		Source:      name.Source,
		Decorations: decos,
		Name:        string(name.Runes),
	}
	if p.peekIs(0, tok.Lt) {
		f.TemplateParams = p.templateParams()
	}
	f.Parameters = p.parameters()
	if p.match(tok.Arrow) != nil {
		ret := p.templatedName()
		f.ReturnType = &ret
	}
	return f
}

func (p *parser) parameters() ast.Parameters {
	l := ast.Parameters{}
	p.expect(tok.Lparen, "function parameter list")
	if p.match(tok.Rparen) == nil {
		for p.err == nil {
			l = append(l, p.parameter())
			if p.match(tok.Comma) == nil {
				break
			}
		}
		p.expect(tok.Rparen, "function parameter list")
	}
	return l
}

func (p *parser) parameter() ast.Parameter {
	if p.peekIs(1, tok.Colon) {
		// name type
		name := p.expect(tok.Identifier, "parameter name")
		p.expect(tok.Colon, "parameter type")
		return ast.Parameter{
			Source: name.Source,
			Name:   string(name.Runes),
			Type:   p.templatedName(),
		}
	}
	// type
	ty := p.templatedName()
	return ast.Parameter{
		Source: ty.Source,
		Type:   ty,
	}
}

func (p *parser) string() string {
	s := p.expect(tok.String, "string")
	return string(s.Runes)
}

func (p *parser) templatedName() ast.TemplatedName {
	name := p.expect(tok.Identifier, "type name")
	m := ast.TemplatedName{Source: name.Source, Name: string(name.Runes)}
	if p.match(tok.Lt) != nil {
		for p.err == nil {
			m.TemplateArgs = append(m.TemplateArgs, p.templatedName())
			if p.match(tok.Comma) == nil {
				break
			}
		}
		p.expect(tok.Gt, "template argument type list")
	}
	return m
}

func (p *parser) templateParams() ast.TemplateParams {
	t := ast.TemplateParams{}
	p.expect(tok.Lt, "template parameter list")
	for p.err == nil && p.peekIs(0, tok.Identifier) {
		t = append(t, p.templateParam())
	}
	p.expect(tok.Gt, "template parameter list")
	return t
}

func (p *parser) templateParam() ast.TemplateParam {
	name := p.match(tok.Identifier)
	t := ast.TemplateParam{
		Source: name.Source,
		Name:   string(name.Runes),
	}
	if p.match(tok.Colon) != nil {
		t.Type = p.templatedName()
	}
	p.match(tok.Comma)
	return t
}

func (p *parser) expect(kind tok.Kind, use string) tok.Token {
	if p.err != nil {
		return tok.Invalid
	}
	t := p.match(kind)
	if t == nil {
		if len(p.tokens) > 0 {
			p.err = fmt.Errorf("%v expected '%v' for %v, got '%v'",
				p.tokens[0].Source, kind, use, p.tokens[0].Kind)
		} else {
			p.err = fmt.Errorf("expected '%v' for %v, but reached end of file", kind, use)
		}
		return tok.Invalid
	}
	return *t
}

func (p *parser) ident(use string) string {
	return string(p.expect(tok.Identifier, use).Runes)
}

// TODO(bclayton): Currently unused, but will be needed for integer bounds
// func (p *parser) integer(use string) int {
// 	t := p.expect(tok.Integer, use)
// 	if t.Kind != tok.Integer {
// 		return 0
// 	}
// 	i, err := strconv.Atoi(string(t.Runes))
// 	if err != nil {
// 		p.err = err
// 		return 0
// 	}
// 	return i
// }

func (p *parser) match(kind tok.Kind) *tok.Token {
	if p.err != nil || len(p.tokens) == 0 {
		return nil
	}
	t := p.tokens[0]
	if t.Kind != kind {
		return nil
	}
	p.tokens = p.tokens[1:]
	return &t
}

func (p *parser) peekIs(i int, kind tok.Kind) bool {
	t := p.peek(i)
	if t == nil {
		return false
	}
	return t.Kind == kind
}

func (p *parser) peek(i int) *tok.Token {
	if len(p.tokens) <= i {
		return nil
	}
	return &p.tokens[i]
}
