// 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 intrinsic definition
// language
package parser

import (
	"fmt"

	"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/ast"
	"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/lexer"
	"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-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]
}
