// Copyright (C) 2016 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 (
	"sort"
	"strconv"

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

func apiNames(rv *resolver, in *ast.API) {
	if in.Index != nil {
		if n, e := strconv.ParseUint(in.Index.Value, 10, 4); e == nil {
			rv.api.Index = new(semantic.Uint8Value)
			*rv.api.Index = semantic.Uint8Value(n)
		} else {
			rv.errorf(in.Index, "cannot convert API index %q into 4-bit unsigned integer", in.Index.Value)
		}
	}
	// Build and register the high level semantic objects
	for _, e := range in.Enums {
		n := &semantic.Enum{AST: e, Named: semantic.Named(e.Name.Value)}
		rv.api.Enums = append(rv.api.Enums, n)
		semantic.Add(rv.api, n)
		rv.addType(n)
	}
	for _, c := range in.Classes {
		n := &semantic.Class{AST: c, Named: semantic.Named(c.Name.Value)}
		rv.api.Classes = append(rv.api.Classes, n)
		semantic.Add(rv.api, n)
		rv.addType(n)
	}
	for _, p := range in.Pseudonyms {
		n := &semantic.Pseudonym{AST: p, Named: semantic.Named(p.Name.Value)}
		rv.api.Pseudonyms = append(rv.api.Pseudonyms, n)
		semantic.Add(rv.api, n)
		rv.addType(n)
	}
	for _, e := range in.Externs {
		n := &semantic.Function{AST: e, Named: semantic.Named(e.Generic.Name.Value), Extern: true}
		rv.api.Externs = append(rv.api.Externs, n)
		semantic.Add(rv.api, n)
	}
	for _, m := range in.Commands {
		f := &semantic.Function{AST: m, Named: semantic.Named(m.Generic.Name.Value)}
		if !m.Parameters[0].This {
			rv.api.Functions = append(rv.api.Functions, f)
			semantic.Add(rv.api, f)
		} else {
			rv.api.Methods = append(rv.api.Methods, f)
		}
	}
	for _, m := range in.Subroutines {
		if m.Parameters[0].This {
			rv.errorf(m.Parameters[0], "cannot use this on subroutines")
			continue
		}
		if len(m.Generic.Arguments) > 0 {
			rv.genericSubroutines[m.Generic.Name.Value] = newGenericSubroutine(rv, m)
		} else {
			f := &semantic.Function{AST: m, Named: semantic.Named(m.Generic.Name.Value), Subroutine: true}
			rv.api.Subroutines = append(rv.api.Subroutines, f)
			semantic.Add(rv.api, f)
		}
	}
	for _, f := range in.Fields {
		n := &semantic.Global{AST: f, Named: semantic.Named(f.Name.Value)}
		rv.api.Globals = append(rv.api.Globals, n)
		semantic.Add(rv.api, n)
	}
	// Add all the alias remaps
	for _, a := range in.Aliases {
		rv.addType(&semantic.Alias{AST: a, Named: semantic.Named(a.Name.Value)})
	}
	for _, c := range in.Definitions {
		n := &semantic.Definition{AST: c, Named: semantic.Named(c.Name.Value)}
		rv.api.Definitions = append(rv.api.Definitions, n)
		rv.addNamed(n)
	}
	for _, e := range in.LabelGroups {
		labeledTypeName := e.LabeledType.Value
		for _, al := range e.Labels {
			sl := &semantic.Label{
				AST:   al,
				Named: semantic.Named(al.Name.Value),
			}

			lls, ok := rv.labels[labeledTypeName]
			if !ok {
				rv.labels[labeledTypeName] = []*semantic.Label{sl}
			} else {
				rv.labels[labeledTypeName] = append(lls, sl)
			}
		}
	}
}

func resolve(rv *resolver) {
	rv.globals = rv.scope

	if rv.api.Imported != nil {
		rv.addSymbols(rv.api.Imported)
	}
	rv.addMembers(rv.api)
	// First resolve enum entries
	for _, e := range rv.api.Enums {
		enum(rv, e)
	}
	// Now build collapsed enum lists
	for _, e := range rv.api.Enums {
		enumEntries(rv, e, e)
	}
	for _, p := range rv.api.Pseudonyms {
		pseudonym(rv, p)
	}
	// Resolve and merge label entries
	resolveLabels(rv)

	for _, c := range rv.api.Definitions {
		definition(rv, c)
	}
	for _, g := range rv.api.Globals {
		global(rv, g)
	}
	for _, e := range rv.api.Externs {
		functionSignature(rv, e)
		functionBody(rv, nil, e)
	}
	for _, c := range rv.api.Classes {
		class(rv, c)
	}
	for _, s := range rv.api.Subroutines {
		functionSignature(rv, s)
		for _, p := range s.FullParameters {
			if p.Type == semantic.AnyType {
				rv.errorf(p, "cannot use any as parameter type on subroutines")
			}
		}
	}
	for _, s := range rv.api.Subroutines {
		functionBody(rv, nil, s)
	}
	for _, f := range rv.api.Functions {
		functionSignature(rv, f)
		functionBody(rv, nil, f)
	}
	for _, f := range rv.api.Subroutines {
		extractCalls(rv, f.Block)
		removeDeadCode(rv, f.Block)
	}
	for _, f := range rv.api.Functions {
		extractCalls(rv, f.Block)
		removeDeadCode(rv, f.Block)
	}
	for _, f := range rv.api.Functions {
		resolveFenceOrder(rv, f, visitedFuncs{})
	}
	for _, m := range rv.api.Methods {
		method(rv, m)
	}
	sort.Sort(functionsByName(rv.api.Externs))
	sort.Sort(slicesByName(rv.api.Slices))
	sort.Sort(mapsByName(rv.api.Maps))
}

func annotations(rv *resolver, in ast.Annotations) semantic.Annotations {
	if len(in) == 0 {
		return nil
	}
	out := semantic.Annotations{}
	for _, a := range in {
		entry := &semantic.Annotation{AST: a, Named: semantic.Named(a.Name.Value)}
		for _, arg := range a.Arguments {
			entry.Arguments = append(entry.Arguments, expression(rv, arg))
		}
		out = append(out, entry)
		rv.mappings.add(a, entry)
	}
	return out
}

func global(rv *resolver, out *semantic.Global) {
	if out.Type != nil {
		return // already resolved.
	}

	// Begin by assigning a void type to the global.
	// This is done to avoid a stack overflow if the global's type resolves to
	// the same global (for example 'x.y x').
	out.Type = semantic.VoidType

	in := out.AST
	out.Annotations = annotations(rv, in.Annotations)
	out.Type = type_(rv, in.Type)
	if isVoid(out.Type) {
		rv.errorf(in, "void typed global variable %s", out.Name())
	}
	if in.Default != nil {
		rv.with(out.Type, func() {
			out.Default = expression(rv, in.Default)
		})
		dt := out.Default.ExpressionType()
		if !assignable(out.Type, dt) {
			rv.errorf(in, "cannot assign %s to %s", typename(dt), typename(out.Type))
		}
	}
	rv.mappings.add(in, out)
}

// slicesByName is used to sort the slice list by name for generated code stability
type slicesByName []*semantic.Slice

func (a slicesByName) Len() int           { return len(a) }
func (a slicesByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a slicesByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }

// mapsByName is used to sort the map list by name for generated code stability
type mapsByName []*semantic.Map

func (a mapsByName) Len() int           { return len(a) }
func (a mapsByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a mapsByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }

// mapsByName is used to sort the map list by name for generated code stability
type functionsByName []*semantic.Function

func (a functionsByName) Len() int           { return len(a) }
func (a functionsByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a functionsByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }

// labelsByName is used to sort a slice of labels by their name
type labelsByName []*semantic.Label

func (a labelsByName) Len() int           { return len(a) }
func (a labelsByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a labelsByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() }
