// 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 resolver

import (
	"fmt"
	"sort"

	"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/ast"
	"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/sem"
	"dawn.googlesource.com/dawn/tools/src/cmd/intrinsic-gen/tok"
)

type resolver struct {
	a *ast.AST
	s *sem.Sem

	globals           scope
	builtins          map[string]*sem.Intrinsic
	unaryOperators    map[string]*sem.Intrinsic
	binaryOperators   map[string]*sem.Intrinsic
	enumEntryMatchers map[*sem.EnumEntry]*sem.EnumMatcher
}

// Resolve processes the AST
func Resolve(a *ast.AST) (*sem.Sem, error) {
	r := resolver{
		a:                 a,
		s:                 sem.New(),
		globals:           newScope(nil),
		builtins:          map[string]*sem.Intrinsic{},
		unaryOperators:    map[string]*sem.Intrinsic{},
		binaryOperators:   map[string]*sem.Intrinsic{},
		enumEntryMatchers: map[*sem.EnumEntry]*sem.EnumMatcher{},
	}
	// Declare and resolve all the enumerators
	for _, e := range a.Enums {
		if err := r.enum(e); err != nil {
			return nil, err
		}
	}
	// Declare and resolve all the ty types
	for _, p := range a.Types {
		if err := r.ty(p); err != nil {
			return nil, err
		}
	}
	// Declare and resolve the type matchers
	for _, m := range a.Matchers {
		if err := r.matcher(m); err != nil {
			return nil, err
		}
	}
	// Declare and resolve the builtins
	for _, f := range a.Builtins {
		if err := r.intrinsic(f, r.builtins, &r.s.Builtins); err != nil {
			return nil, err
		}
	}
	// Declare and resolve the unary and binary operators
	for _, o := range a.Operators {
		switch len(o.Parameters) {
		case 1:
			if err := r.intrinsic(o, r.unaryOperators, &r.s.UnaryOperators); err != nil {
				return nil, err
			}
		case 2:
			if err := r.intrinsic(o, r.binaryOperators, &r.s.BinaryOperators); err != nil {
				return nil, err
			}
		default:
			return nil, fmt.Errorf("%v operators must have either 1 or 2 parameters", o.Source)
		}
	}

	// Calculate the unique parameter names
	r.s.UniqueParameterNames = r.calculateUniqueParameterNames()

	return r.s, nil
}

// enum() resolves an enum declaration.
// The resulting sem.Enum is appended to Sem.Enums, and the enum and all its
// entries are registered with the global scope.
func (r *resolver) enum(e ast.EnumDecl) error {
	s := &sem.Enum{
		Decl: e,
		Name: e.Name,
	}

	// Register the enum
	r.s.Enums = append(r.s.Enums, s)
	if err := r.globals.declare(s, e.Source); err != nil {
		return err
	}

	// Register each of the enum entries
	for _, ast := range e.Entries {
		entry := &sem.EnumEntry{
			Name: ast.Name,
			Enum: s,
		}
		if internal := ast.Decorations.Take("internal"); internal != nil {
			entry.IsInternal = true
			if len(internal.Values) != 0 {
				return fmt.Errorf("%v unexpected value for internal decoration", ast.Source)
			}
		}
		if len(ast.Decorations) != 0 {
			return fmt.Errorf("%v unknown decoration", ast.Decorations[0].Source)
		}
		if err := r.globals.declare(entry, e.Source); err != nil {
			return err
		}
		s.Entries = append(s.Entries, entry)
	}

	return nil
}

// ty() resolves a type declaration.
// The resulting sem.Type is appended to Sem.Types, and the type is registered
// with the global scope.
func (r *resolver) ty(a ast.TypeDecl) error {
	t := &sem.Type{
		Decl: a,
		Name: a.Name,
	}

	// Register the type
	r.s.Types = append(r.s.Types, t)
	if err := r.globals.declare(t, a.Source); err != nil {
		return err
	}

	// Create a new scope for resolving template parameters
	s := newScope(&r.globals)

	// Resolve the type template parameters
	templateParams, err := r.templateParams(&s, a.TemplateParams)
	if err != nil {
		return err
	}
	t.TemplateParams = templateParams

	// Scan for decorations
	if d := a.Decorations.Take("display"); d != nil {
		if len(d.Values) != 1 {
			return fmt.Errorf("%v expected a single value for 'display' decoration", d.Source)
		}
		t.DisplayName = d.Values[0]
	}
	if len(a.Decorations) != 0 {
		return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source)
	}

	return nil
}

// matcher() resolves a match declaration to either a sem.TypeMatcher or
// sem.EnumMatcher.
// The resulting matcher is appended to either Sem.TypeMatchers or
// Sem.EnumMatchers, and is registered with the global scope.
func (r *resolver) matcher(a ast.MatcherDecl) error {
	// Determine whether this is a type matcher or enum matcher by resolving the
	// first option
	firstOption, err := r.lookupNamed(&r.globals, a.Options[0])
	if err != nil {
		return err
	}

	// Resolve to a sem.TypeMatcher or a sem.EnumMatcher
	switch firstOption := firstOption.(type) {
	case *sem.Type:
		options := map[sem.Named]tok.Source{}
		m := &sem.TypeMatcher{
			Decl: a,
			Name: a.Name,
		}

		// Register the matcher
		r.s.TypeMatchers = append(r.s.TypeMatchers, m)
		if err := r.globals.declare(m, a.Source); err != nil {
			return err
		}

		// Resolve each of the types in the options list
		for _, ast := range m.Decl.Options {
			ty, err := r.lookupType(&r.globals, ast)
			if err != nil {
				return err
			}
			m.Types = append(m.Types, ty)
			if s, dup := options[ty]; dup {
				return fmt.Errorf("%v duplicate option '%v' in matcher\nFirst declared here: %v", ast.Source, ast.Name, s)
			}
			options[ty] = ast.Source
		}

		return nil

	case *sem.EnumEntry:
		enum := firstOption.Enum
		m := &sem.EnumMatcher{
			Decl: a,
			Name: a.Name,
			Enum: enum,
		}

		// Register the matcher
		r.s.EnumMatchers = append(r.s.EnumMatchers, m)
		if err := r.globals.declare(m, a.Source); err != nil {
			return err
		}

		// Resolve each of the enums in the options list
		for _, ast := range m.Decl.Options {
			entry := enum.FindEntry(ast.Name)
			if entry == nil {
				return fmt.Errorf("%v enum '%v' does not contain '%v'", ast.Source, enum.Name, ast.Name)
			}
			m.Options = append(m.Options, entry)
		}

		return nil
	}
	return fmt.Errorf("'%v' cannot be used for matcher", a.Name)
}

// intrinsic() resolves a intrinsic overload declaration.
// The the first overload for the intrinsic creates and appends the sem.Intrinsic
// to Sem.Intrinsics. Subsequent overloads append their resolved overload to the
// sem.intrinsic.Overloads list.
func (r *resolver) intrinsic(
	a ast.IntrinsicDecl,
	intrinsicsByName map[string]*sem.Intrinsic,
	semIntrinsics *[]*sem.Intrinsic) error {
	// If this is the first overload of the intrinsic, create and register the
	// semantic intrinsic.
	intrinsic := intrinsicsByName[a.Name]
	if intrinsic == nil {
		intrinsic = &sem.Intrinsic{Name: a.Name}
		intrinsicsByName[a.Name] = intrinsic
		*semIntrinsics = append(*semIntrinsics, intrinsic)
	}

	// Create a new scope for resolving template parameters
	s := newScope(&r.globals)

	// Resolve the declared template parameters
	templateParams, err := r.templateParams(&s, a.TemplateParams)
	if err != nil {
		return err
	}

	// Construct the semantic overload
	overload := &sem.Overload{
		Decl:           a,
		Intrinsic:      intrinsic,
		Parameters:     make([]sem.Parameter, len(a.Parameters)),
		TemplateParams: templateParams,
	}

	// Process overload decorations
	if stageDeco := a.Decorations.Take("stage"); stageDeco != nil {
		for stageDeco != nil {
			for _, stage := range stageDeco.Values {
				switch stage {
				case "vertex":
					overload.CanBeUsedInStage.Vertex = true
				case "fragment":
					overload.CanBeUsedInStage.Fragment = true
				case "compute":
					overload.CanBeUsedInStage.Compute = true
				default:
					return fmt.Errorf("%v unknown stage '%v'", stageDeco.Source, stage)
				}
			}
			stageDeco = a.Decorations.Take("stage")
		}
	} else {
		overload.CanBeUsedInStage = sem.StageUses{
			Vertex:   true,
			Fragment: true,
			Compute:  true,
		}
	}
	if deprecated := a.Decorations.Take("deprecated"); deprecated != nil {
		overload.IsDeprecated = true
		if len(deprecated.Values) != 0 {
			return fmt.Errorf("%v unexpected value for deprecated decoration", deprecated.Source)
		}
	}
	if len(a.Decorations) != 0 {
		return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source)
	}

	// Append the overload to the intrinsic
	intrinsic.Overloads = append(intrinsic.Overloads, overload)

	// Sort the template parameters by resolved type. Append these to
	// sem.Overload.OpenTypes or sem.Overload.OpenNumbers based on their kind.
	for _, param := range templateParams {
		switch param := param.(type) {
		case *sem.TemplateTypeParam:
			overload.OpenTypes = append(overload.OpenTypes, param)
		case *sem.TemplateEnumParam, *sem.TemplateNumberParam:
			overload.OpenNumbers = append(overload.OpenNumbers, param)
		}
	}

	// Update high-water marks of open types / numbers
	if r.s.MaxOpenTypes < len(overload.OpenTypes) {
		r.s.MaxOpenTypes = len(overload.OpenTypes)
	}
	if r.s.MaxOpenNumbers < len(overload.OpenNumbers) {
		r.s.MaxOpenNumbers = len(overload.OpenNumbers)
	}

	// Resolve the parameters
	for i, p := range a.Parameters {
		usage, err := r.fullyQualifiedName(&s, p.Type)
		if err != nil {
			return err
		}
		overload.Parameters[i] = sem.Parameter{
			Name: p.Name,
			Type: usage,
		}
	}

	// Resolve the return type
	if a.ReturnType != nil {
		usage, err := r.fullyQualifiedName(&s, *a.ReturnType)
		if err != nil {
			return err
		}
		switch usage.Target.(type) {
		case *sem.Type, *sem.TemplateTypeParam:
			overload.ReturnType = &usage
		default:
			return fmt.Errorf("%v cannot use '%v' as return type. Must be a type or template type", a.ReturnType.Source, a.ReturnType.Name)
		}
	}

	return nil
}

// fullyQualifiedName() resolves the ast.TemplatedName to a sem.FullyQualifiedName.
func (r *resolver) fullyQualifiedName(s *scope, arg ast.TemplatedName) (sem.FullyQualifiedName, error) {
	target, err := r.lookupNamed(s, arg)
	if err != nil {
		return sem.FullyQualifiedName{}, err
	}

	if entry, ok := target.(*sem.EnumEntry); ok {
		// The target resolved to an enum entry.
		// Automagically transform this into a synthetic matcher with a single
		// option. i.e.
		// This:
		//   enum E{ a b c }
		//   fn F(b)
		// Becomes:
		//   enum E{ a b c }
		//   matcher b
		//   fn F(b)
		// We don't really care right now that we have a symbol collision
		// between E.b and b, as the generators return different names for
		// these.
		matcher, ok := r.enumEntryMatchers[entry]
		if !ok {
			matcher = &sem.EnumMatcher{
				Name:    entry.Name,
				Enum:    entry.Enum,
				Options: []*sem.EnumEntry{entry},
			}
			r.enumEntryMatchers[entry] = matcher
			r.s.EnumMatchers = append(r.s.EnumMatchers, matcher)
		}
		target = matcher
	}

	fqn := sem.FullyQualifiedName{
		Target:            target,
		TemplateArguments: make([]interface{}, len(arg.TemplateArgs)),
	}
	for i, a := range arg.TemplateArgs {
		arg, err := r.fullyQualifiedName(s, a)
		if err != nil {
			return sem.FullyQualifiedName{}, err
		}
		fqn.TemplateArguments[i] = arg
	}
	return fqn, nil
}

// templateParams() resolves the ast.TemplateParams into list of sem.TemplateParam.
// Each sem.TemplateParam is registered with the scope s.
func (r *resolver) templateParams(s *scope, l ast.TemplateParams) ([]sem.TemplateParam, error) {
	out := []sem.TemplateParam{}
	for _, ast := range l {
		param, err := r.templateParam(ast)
		if err != nil {
			return nil, err
		}
		s.declare(param, ast.Source)
		out = append(out, param)
	}
	return out, nil
}

// templateParams() resolves the ast.TemplateParam into sem.TemplateParam, which
// is either a sem.TemplateEnumParam or a sem.TemplateTypeParam.
func (r *resolver) templateParam(a ast.TemplateParam) (sem.TemplateParam, error) {
	if a.Type.Name == "num" {
		return &sem.TemplateNumberParam{Name: a.Name}, nil
	}

	if a.Type.Name != "" {
		resolved, err := r.lookupNamed(&r.globals, a.Type)
		if err != nil {
			return nil, err
		}
		switch r := resolved.(type) {
		case *sem.Enum:
			return &sem.TemplateEnumParam{Name: a.Name, Enum: r}, nil
		case *sem.EnumMatcher:
			return &sem.TemplateEnumParam{Name: a.Name, Enum: r.Enum, Matcher: r}, nil
		case *sem.TypeMatcher:
			return &sem.TemplateTypeParam{Name: a.Name, Type: r}, nil
		default:
			return nil, fmt.Errorf("%v invalid template parameter type '%v'", a.Source, a.Type.Name)
		}
	}

	return &sem.TemplateTypeParam{Name: a.Name}, nil
}

// lookupType() searches the scope `s` and its ancestors for the sem.Type with
// the given name.
func (r *resolver) lookupType(s *scope, a ast.TemplatedName) (*sem.Type, error) {
	resolved, err := r.lookupNamed(s, a)
	if err != nil {
		return nil, err
	}
	// Something with the given name was found...
	if ty, ok := resolved.(*sem.Type); ok {
		return ty, nil
	}
	// ... but that something was not a sem.Type
	return nil, fmt.Errorf("%v '%v' resolves to %v but type is expected", a.Source, a.Name, describe(resolved))
}

// lookupNamed() searches `s` and its ancestors for the sem.Named object with
// the given name. If there are template arguments for the name `a`, then
// lookupNamed() performs basic validation that those arguments can be passed
// to the named object.
func (r *resolver) lookupNamed(s *scope, a ast.TemplatedName) (sem.Named, error) {
	target := s.lookup(a.Name)
	if target == nil {
		return nil, fmt.Errorf("%v cannot resolve '%v'", a.Source, a.Name)
	}

	// Something with the given name was found...
	var params []sem.TemplateParam
	var ty sem.ResolvableType
	switch target := target.object.(type) {
	case *sem.Type:
		ty = target
		params = target.TemplateParams
	case *sem.TypeMatcher:
		ty = target
		params = target.TemplateParams
	case sem.TemplateParam:
		if len(a.TemplateArgs) != 0 {
			return nil, fmt.Errorf("%v '%v' template parameters do not accept template arguments", a.Source, a.Name)
		}
		return target.(sem.Named), nil
	case sem.Named:
		return target, nil
	default:
		panic(fmt.Errorf("Unknown resolved type %T", target))
	}
	// ... and that something takes template parameters
	// Check the number of templated name template arguments match the number of
	// templated parameters for the target.
	args := a.TemplateArgs
	if len(params) != len(args) {
		return nil, fmt.Errorf("%v '%v' requires %d template arguments, but %d were provided", a.Source, a.Name, len(params), len(args))
	}

	// Check templated name template argument kinds match the parameter kinds
	for i, ast := range args {
		param := params[i]
		arg, err := r.lookupNamed(s, args[i])
		if err != nil {
			return nil, err
		}

		if err := checkCompatible(arg, param); err != nil {
			return nil, fmt.Errorf("%v %w", ast.Source, err)
		}
	}
	return ty, nil
}

// calculateUniqueParameterNames() iterates over all the parameters of all
// builtin overloads, calculating the list of unique parameter names
func (r *resolver) calculateUniqueParameterNames() []string {
	set := map[string]struct{}{"": {}}
	names := []string{}
	for _, intrinsics := range [][]*sem.Intrinsic{
		r.s.Builtins,
		r.s.UnaryOperators,
		r.s.BinaryOperators,
	} {
		for _, i := range intrinsics {
			for _, o := range i.Overloads {
				for _, p := range o.Parameters {
					if _, dup := set[p.Name]; !dup {
						set[p.Name] = struct{}{}
						names = append(names, p.Name)
					}
				}
			}
		}
	}
	sort.Strings(names)
	return names
}

// describe() returns a string describing a sem.Named
func describe(n sem.Named) string {
	switch n := n.(type) {
	case *sem.Type:
		return "type '" + n.Name + "'"
	case *sem.TypeMatcher:
		return "type matcher '" + n.Name + "'"
	case *sem.Enum:
		return "enum '" + n.Name + "'"
	case *sem.EnumMatcher:
		return "enum matcher '" + n.Name + "'"
	case *sem.TemplateTypeParam:
		return "template type"
	case *sem.TemplateEnumParam:
		return "template enum '" + n.Enum.Name + "'"
	case *sem.EnumEntry:
		return "enum entry '" + n.Enum.Name + "." + n.Name + "'"
	case *sem.TemplateNumberParam:
		return "template number"
	default:
		panic(fmt.Errorf("unhandled type %T", n))
	}
}

// checkCompatible() returns an error if `arg` cannot be used as an argument for
// a parameter of `param`.
func checkCompatible(arg, param sem.Named) error {
	// asEnum() returns the underlying sem.Enum if n is a enum matcher,
	// templated enum parameter or an enum entry, otherwise nil
	asEnum := func(n sem.Named) *sem.Enum {
		switch n := n.(type) {
		case *sem.EnumMatcher:
			return n.Enum
		case *sem.TemplateEnumParam:
			return n.Enum
		case *sem.EnumEntry:
			return n.Enum
		default:
			return nil
		}
	}

	if arg := asEnum(arg); arg != nil {
		param := asEnum(param)
		if arg == param {
			return nil
		}
	}

	anyNumber := "any number"
	// asNumber() returns anyNumber if n is a TemplateNumberParam.
	// TODO(bclayton): Once we support number ranges [e.g.: fn F<N: 1..4>()], we
	// should check number ranges are compatible
	asNumber := func(n sem.Named) interface{} {
		switch n.(type) {
		case *sem.TemplateNumberParam:
			return anyNumber
		default:
			return nil
		}
	}

	if arg := asNumber(arg); arg != nil {
		param := asNumber(param)
		if arg == param {
			return nil
		}
	}

	anyType := &sem.Type{}
	// asNumber() returns the sem.Type, sem.TypeMatcher if the named object
	// resolves to one of these, or anyType if n is a unconstrained template
	// type parameter.
	asResolvableType := func(n sem.Named) sem.ResolvableType {
		switch n := n.(type) {
		case *sem.TemplateTypeParam:
			if n.Type != nil {
				return n.Type
			}
			return anyType
		case *sem.Type:
			return n
		case *sem.TypeMatcher:
			return n
		default:
			return nil
		}
	}

	if arg := asResolvableType(arg); arg != nil {
		param := asResolvableType(param)
		if arg == param || param == anyType {
			return nil
		}
	}

	return fmt.Errorf("cannot use %v as %v", describe(arg), describe(param))
}

// scope is a basic hierarchical name to object table
type scope struct {
	objects map[string]objectAndSource
	parent  *scope
}

// objectAndSource is a sem.Named object with a source
type objectAndSource struct {
	object sem.Named
	source tok.Source
}

// newScope returns a newly initalized scope
func newScope(parent *scope) scope {
	return scope{objects: map[string]objectAndSource{}, parent: parent}
}

// lookup() searches the scope and then its parents for the symbol with the
// given name.
func (s *scope) lookup(name string) *objectAndSource {
	if o, found := s.objects[name]; found {
		return &o
	}
	if s.parent == nil {
		return nil
	}
	return s.parent.lookup(name)
}

// declare() declares the symbol with the given name, erroring on symbol
// collision.
func (s *scope) declare(object sem.Named, source tok.Source) error {
	name := object.GetName()
	if existing := s.lookup(name); existing != nil {
		return fmt.Errorf("%v '%v' already declared\nFirst declared here: %v", source, name, existing.source)
	}
	s.objects[name] = objectAndSource{object, source}
	return nil
}
