// Copyright (C) 2014 The Android Open Source Project
//
// 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"
	"reflect"

	"android.googlesource.com/platform/tools/gpu/api/semantic"
	"android.googlesource.com/platform/tools/gpu/parse"
)

type context struct {
	errors parse.ErrorList
	api    *semantic.API
	types  map[string]semantic.Type
	scope  *scope
	nextId uint64
}

type scope struct {
	outer     *scope
	entries   map[string][]interface{}
	inferType semantic.Type
	block     *[]interface{}
}

func (ctx *context) errorf(at interface{}, message string, args ...interface{}) {
	var n parse.Fragment
	if at != nil {
		v := reflect.ValueOf(at)
		v = reflect.Indirect(v)
		if v.IsValid() {
			if fv := v.FieldByName("CST"); fv.IsValid() {
				if !fv.IsNil() {
					n = fv.Interface().(parse.Fragment)
				} else {
					ctx.errors.Add(nil, nil, "Error at node with nil CST field in %T", at)
				}
			}
		}
	}
	ctx.errors.Add(nil, n, message, args...)
}

func (ctx *context) icef(at interface{}, message string, args ...interface{}) {
	ctx.errorf(at, "INTERNAL ERROR: "+message, args...)
}

// with evaluates the action within a new nested scope.
// The scope is available as ctx.scope, and the original scope is
// restored before this function returns.
// Type t is used for type inference within the new scope (for
// instance when resolving untyped numeric constants)
func (ctx *context) with(t semantic.Type, action func()) {
	original := ctx.scope
	ctx.scope = &scope{
		outer:     ctx.scope,
		block:     ctx.scope.block,
		entries:   map[string][]interface{}{},
		inferType: t,
	}
	defer func() { ctx.scope = original }()
	action()
}

// add binds a name to a specific value within the current and nested scopes.
func (ctx *context) add(name string, value interface{}) {
	list, _ := ctx.scope.entries[name]
	ctx.scope.entries[name] = append(list, value)
}

// find searches the scope stack for a bindings that matches the name.
func (ctx *context) find(name string) []interface{} {
	if ctx.scope == nil {
		return nil
	}
	result, _ := ctx.scope.entries[name]
	for search := ctx.scope.outer; search != nil; search = search.outer {
		list, ok := search.entries[name]
		if ok && len(list) > 0 {
			result = append(result, list...)
		}
	}
	return result
}

// disambiguate takes a list of possible scope values and attempts to see if
// one of them is unambiguously the right choice in the current context.
// For instance, if the values are all enum entries but only one of them
// matches the current enum inference.
func (ctx *context) disambiguate(matches []interface{}) []interface{} {
	if len(matches) <= 1 {
		return matches
	}
	var enum *semantic.Enum
	for test := ctx.scope; test != nil; test = test.outer {
		if test.inferType != nil {
			if e, ok := test.inferType.(*semantic.Enum); ok {
				enum = e
				break
			}
		}
	}
	if enum == nil {
		// No disambiguating enums present
		return matches
	}
	var res *semantic.EnumEntry
	for _, m := range matches {
		if ev, ok := m.(*semantic.EnumEntry); ok {
			if enum == ev.Enum {
				// We found a disambiguation match
				res = ev
			}
		} else {
			// Non enum match found
			return matches
		}
	}
	if res == nil {
		return matches
	}
	// Matched exactly once
	return []interface{}{res}
}

// get searches the scope stack for a bindings that matches the name.
// If it cannot find exactly 1 unambiguous match, it reports an error, and
// nil is returned.
func (ctx *context) get(at interface{}, name string) interface{} {
	matches := ctx.disambiguate(ctx.find(name))
	switch len(matches) {
	case 0:
		ctx.errorf(at, "Unknown identifier %s", name)
		return nil
	case 1:
		return matches[0]
	default:
		possibilities := ""
		for i, m := range matches {
			if i > 0 {
				possibilities += ", "
			}
			switch t := m.(type) {
			case *semantic.EnumEntry:
				possibilities += fmt.Sprintf("%s.%s", t.Enum.Name, t.Name)
			case *semantic.Parameter:
				possibilities += fmt.Sprintf("parameter %q", t.Name)
			case semantic.Type:
				possibilities += fmt.Sprintf("type %q [%T]", typename(t), t)
			default:
				possibilities += fmt.Sprintf("[%T]%v", t, t)
			}
		}
		ctx.errorf(at, "Ambiguous identifier %q [using %s].\n Could be: %s", name, typename(ctx.scope.inferType), possibilities)
		return nil
	}
}

func (ctx *context) addType(t semantic.Type) {
	name := t.Typename()
	_, present := ctx.types[name]
	if present {
		ctx.errorf(t, "Duplicate type %s", name)
	}
	ctx.types[name] = t
}

func (ctx *context) findType(at interface{}, name string) semantic.Type {
	t, found := ctx.types[name]
	if !found {
		return nil
	}
	return t
}

func (ctx *context) addStatement(s interface{}) {
	if _, isInvalid := s.(invalid); isInvalid {
		return
	}
	*ctx.scope.block = append(*ctx.scope.block, s)
}

func (ctx *context) uid() uint64 {
	id := ctx.nextId
	ctx.nextId++
	return id
}
