// 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 (
	"strconv"
	"strings"

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

func type_(ctx *context, in interface{}) semantic.Type {
	switch in := in.(type) {
	case *ast.Identifier:
		return simpleType(ctx, in)
	case *ast.MapType:
		return mapType(ctx, in)
	case *ast.ArrayType:
		return arrayType(ctx, in)
	case *ast.StaticArrayType:
		return staticArrayType(ctx, in)
	case *ast.PointerType:
		return pointerType(ctx, in)
	default:
		ctx.errorf(in, "Unhandled typeref %T found", in)
		return semantic.VoidType
	}
}

func simpleType(ctx *context, in *ast.Identifier) semantic.Type {
	name := in.Value
	out := ctx.findType(in, name)
	if out == nil {
		ctx.errorf(in, "Type %s not found", name)
		return semantic.VoidType
	}
	if a, ok := out.(*alias); ok {
		if a.To == nil {
			a.To = type_(ctx, a.AST.To)
		}
		return a.To
	}
	return out
}

func mapType(ctx *context, in *ast.MapType) *semantic.Map {
	kt := type_(ctx, in.KeyType)
	vt := type_(ctx, in.ValueType)
	name := strings.Title(vt.Typename()) + "_" + kt.Typename() + "Map"
	for _, m := range ctx.api.Maps {
		if m.Name == name {
			if !equal(kt, m.KeyType) {
				ctx.icef(in, "Map %s found with non matching key, got %s expected %s", name, typename(m.KeyType), typename(kt))
			}
			if !equal(vt, m.ValueType) {
				ctx.icef(in, "Map %s found with non matching value, got %s expected %s", name, typename(m.ValueType), typename(vt))
			}
			return m
		}
	}
	out := &semantic.Map{
		Name:      name,
		KeyType:   kt,
		ValueType: vt,
		Members:   semantic.Members{},
	}
	for _, f := range []*semantic.Function{
		&semantic.Function{Name: "Get",
			FullParameters: []*semantic.Parameter{{},
				{Name: "key", Type: kt},
				{Name: "value", Type: vt},
				{Type: vt},
			},
		},
		&semantic.Function{Name: "Delete",
			FullParameters: []*semantic.Parameter{{},
				{Name: "key", Type: kt},
			},
		},
		&semantic.Function{Name: "Range",
			FullParameters: []*semantic.Parameter{{},
				{Type: semantic.AnyType},
			},
		},
	} {
		f.Owner = out
		f.This = f.FullParameters[0]
		f.This.Name = "self"
		f.This.Type = out
		last := f.FullParameters[len(f.FullParameters)-1]
		if last.Name == "" {
			f.Return = f.FullParameters[len(f.FullParameters)-1]
			f.Return.Output = true
			f.Outputs = append(f.Outputs, f.Return)
		} else {
			f.Return = &semantic.Parameter{Type: semantic.VoidType}
		}
		out.Members[f.Name] = f
	}
	ctx.api.Maps = append(ctx.api.Maps, out)
	return out
}

func arrayType(ctx *context, in *ast.ArrayType) *semantic.Array {
	vt := type_(ctx, in.ValueType)
	name := strings.Title(vt.Typename()) + "Array"
	for _, a := range ctx.api.Arrays {
		if a.Name == name {
			if !equal(vt, a.ValueType) {
				ctx.icef(in, "Array %s found with non matching value, got %s expected %s", name, typename(a.ValueType), typename(vt))
			}
			return a
		}
	}
	out := &semantic.Array{
		Name:      name,
		ValueType: vt,
	}
	ctx.api.Arrays = append(ctx.api.Arrays, out)
	return out
}

func staticArrayType(ctx *context, in *ast.StaticArrayType) *semantic.StaticArray {
	vt := type_(ctx, in.ValueType)
	name := strings.Title(vt.Typename()) + "StaticArray"
	for _, a := range ctx.api.StaticArrays {
		if a.Name == name {
			if !equal(vt, a.ValueType) {
				ctx.icef(in, "Static array %s found with non matching value, got %s expected %s", name, typename(a.ValueType), typename(vt))
			}
			return a
		}
	}
	out := &semantic.StaticArray{
		Name:      name,
		ValueType: vt,
	}
	ctx.with(semantic.Uint32Type, func() {
		for _, d := range in.Dimensions {
			e := expression(ctx, d)
			if n, ok := e.(semantic.Uint32Value); ok {
				out.Dimensions = append(out.Dimensions, n)
			} else {
				ctx.errorf(in, "Array dimension must be a constant number, got %T", e)
			}
		}
	})
	ctx.api.StaticArrays = append(ctx.api.StaticArrays, out)
	return out
}

func getPointerType(ctx *context, at interface{}, to semantic.Type) *semantic.Pointer {
	name := strings.Title(to.Typename()) + "Ref"
	for _, p := range ctx.api.Pointers {
		if p.Name == name {
			if !equal(to, p.To) {
				ctx.icef(at, "Pointer %s found with non matching value, got %s expected %s", name, typename(p.To), typename(to))
			}
			return p
		}
	}
	out := &semantic.Pointer{
		Name: name,
		To:   to,
	}
	ctx.api.Pointers = append(ctx.api.Pointers, out)
	return out
}

func pointerType(ctx *context, in *ast.PointerType) *semantic.Pointer {
	vt := type_(ctx, in.To)
	return getPointerType(ctx, in, vt)
}

func enum(ctx *context, out *semantic.Enum) {
	if len(out.AllEntries) > 0 {
		// Already resolved.
		return
	}
	in := out.AST
	out.Annotations = annotations(ctx, in.Annotations)
	out.IsBitfield = in.IsBitfield
	for _, e := range in.Entries {
		v, err := strconv.ParseUint(e.Value.Value, 0, 32)
		if err != nil {
			ctx.errorf(e, "could not parse %s as uint32", e.Value)
			continue
		}
		entry := &semantic.EnumEntry{
			AST:   e,
			Enum:  out,
			Name:  e.Name.Value,
			Value: uint32(v),
		}
		out.Entries = append(out.Entries, entry)
		out.AllEntries = append(out.AllEntries, entry)
	}
	for _, extends := range in.Extends {
		t := ctx.findType(extends, extends.Value)
		if e, ok := t.(*semantic.Enum); !ok {
			ctx.errorf(extends, "non enum entry %s in extension list", typename(t))
		} else {
			out.Extends = append(out.Extends, e)
			enum(ctx, e)
			for _, entry := range e.AllEntries {
				copy := *entry
				copy.Enum = out
				out.AllEntries = append(out.AllEntries, &copy)
			}
		}
	}
	for _, entry := range out.AllEntries {
		ctx.add(entry.Name, entry)
	}
}

func class(ctx *context, out *semantic.Class) {
	in := out.AST
	out.Annotations = annotations(ctx, in.Annotations)
	for _, extends := range in.Extends {
		t := ctx.findType(extends, extends.Value)
		if c, ok := t.(*semantic.Class); !ok {
			ctx.errorf(extends, "non class entry %s in extension list", typename(t))
		} else {
			out.Extends = append(out.Extends, c)
			c.ExtendedBy = append(c.ExtendedBy, out)
		}
	}
	out.Fields = make([]*semantic.Field, len(in.Fields))
	for i, f := range in.Fields {
		field := field(ctx, f, out)
		out.Fields[i] = field
		out.Members[field.Name] = field
	}
}

func field(ctx *context, in *ast.Field, class *semantic.Class) *semantic.Field {
	out := &semantic.Field{AST: in, Name: in.Name.Value, Class: class}
	out.Annotations = annotations(ctx, in.Annotations)
	out.Type = type_(ctx, in.Type)
	if in.Default != nil {
		ctx.with(out.Type, func() {
			out.Default = expression(ctx, in.Default)
		})
		dt := out.Default.ExpressionType()
		if !assignable(out.Type, dt) {
			ctx.errorf(in, "cannot assign %s to %s", typename(dt), typename(out.Type))
		}
	}
	return out
}

func pseudonym(ctx *context, out *semantic.Pseudonym) {
	in := out.AST
	out.Annotations = annotations(ctx, in.Annotations)
	out.To = type_(ctx, in.To)
}

func typename(e semantic.Type) string {
	if e == nil {
		return "missing"
	} else {
		return e.Typename()
	}
}
