// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package compile

import (
	"fmt"

	"v.io/v23/vdl"
	"v.io/x/ref/lib/vdl/parse"
)

// TypeDef represents a user-defined named type definition in the compiled
// results.
type TypeDef struct {
	NamePos            // name, parse position and docs
	Exported bool      // is this type definition exported?
	Type     *vdl.Type // type of this type definition

	// BaseType is the type that Type is based on.  The BaseType may be named or
	// unnamed.  E.g.
	//                                 BaseType
	//   type Bool    bool;            bool
	//   type Bool2   Bool;            Bool
	//   type List    []int32;         []int32
	//   type List2   List;            List
	//   type Struct  struct{A bool};  struct{A bool}
	//   type Struct2 Struct;          Struct
	BaseType *vdl.Type

	LabelDoc       []string // [valid for enum] docs for each label
	LabelDocSuffix []string // [valid for enum] suffix docs for each label
	FieldDoc       []string // [valid for struct, union] docs for each field
	FieldDocSuffix []string // [valid for struct, union] suffix docs for each field
	File           *File    // parent file that this type is defined in
}

func (x *TypeDef) String() string {
	c := *x
	c.File = nil // avoid infinite loop
	return fmt.Sprintf("%+v", c)
}

// compileTypeDefs is the "entry point" to the rest of this file.  It takes the
// types defined in pfiles and compiles them into TypeDefs in pkg.
func compileTypeDefs(pkg *Package, pfiles []*parse.File, env *Env) {
	td := typeDefiner{
		pkg:      pkg,
		pfiles:   pfiles,
		env:      env,
		tbuilder: &vdl.TypeBuilder{},
		builders: make(map[string]*typeDefBuilder),
	}
	if td.Declare(); !env.Errors.IsEmpty() {
		return
	}
	if td.Define(); !env.Errors.IsEmpty() {
		return
	}
	td.Build()
	// TODO(toddw): should we disallow inter-file cyclic type dependencies?  That
	// might be an issue for generated C++.
}

// typeDefiner defines types in a package.  This is split into three phases:
// 1) Declare ensures local type references can be resolved.
// 2) Define describes each type, resolving named references.
// 3) Build builds all types.
//
// It holds a builders map from type name to typeDefBuilder, where the
// typeDefBuilder is responsible for compiling and defining a single type.
type typeDefiner struct {
	pkg      *Package
	pfiles   []*parse.File
	env      *Env
	tbuilder *vdl.TypeBuilder
	builders map[string]*typeDefBuilder
}

type typeDefBuilder struct {
	def     *TypeDef
	ptype   parse.Type
	pending vdl.PendingNamed // named type that's being built
	base    vdl.PendingType  // base type that pending is based on
}

// Declare creates builders for each type defined in the package.
func (td typeDefiner) Declare() {
	for ix := range td.pkg.Files {
		file, pfile := td.pkg.Files[ix], td.pfiles[ix]
		for _, pdef := range pfile.TypeDefs {
			detail := identDetail("type", file, pdef.Pos)
			if err := file.DeclareIdent(pdef.Name, detail); err != nil {
				td.env.prefixErrorf(file, pdef.Pos, err, "type %s name conflict", pdef.Name)
				continue
			}
			td.builders[pdef.Name] = td.makeTypeDefBuilder(file, pdef)
		}
	}
}

func (td typeDefiner) makeTypeDefBuilder(file *File, pdef *parse.TypeDef) *typeDefBuilder {
	export, err := validIdent(pdef.Name, reservedNormal)
	if err != nil {
		td.env.prefixErrorf(file, pdef.Pos, err, "type %s invalid name", pdef.Name)
		return nil
	}
	ret := new(typeDefBuilder)
	ret.def = &TypeDef{NamePos: NamePos(pdef.NamePos), Exported: export, File: file}
	ret.ptype = pdef.Type
	// We use the qualified name to actually name the type, to ensure types
	// defined in separate packages are hash-consed separately.
	qname := file.Package.QualifiedName(pdef.Name)
	ret.pending = td.tbuilder.Named(qname)
	switch pt := pdef.Type.(type) {
	case *parse.TypeEnum:
		ret.def.LabelDoc = make([]string, len(pt.Labels))
		ret.def.LabelDocSuffix = make([]string, len(pt.Labels))
		for index, plabel := range pt.Labels {
			if err := validExportedIdent(plabel.Name, reservedFirstRuneLower); err != nil {
				td.env.prefixErrorf(file, plabel.Pos, err, "invalid enum label name %s", plabel.Name)
				return nil
			}
			ret.def.LabelDoc[index] = plabel.Doc
			ret.def.LabelDocSuffix[index] = plabel.DocSuffix
		}
	case *parse.TypeStruct:
		ret = attachFieldDoc(ret, pt.Fields, file, td.env)
	case *parse.TypeUnion:
		ret = attachFieldDoc(ret, pt.Fields, file, td.env)
	}
	return ret
}

func attachFieldDoc(ret *typeDefBuilder, fields []*parse.Field, file *File, env *Env) *typeDefBuilder {
	ret.def.FieldDoc = make([]string, len(fields))
	ret.def.FieldDocSuffix = make([]string, len(fields))
	for index, pfield := range fields {
		if err := validExportedIdent(pfield.Name, reservedFirstRuneLower); err != nil {
			env.prefixErrorf(file, pfield.Pos, err, "invalid field name %s", pfield.Name)
			return nil
		}
		ret.def.FieldDoc[index] = pfield.Doc
		ret.def.FieldDocSuffix[index] = pfield.DocSuffix
	}
	return ret
}

// Define uses the builders to describe each type.  Named types defined in
// other packages must have already been compiled, and in env.  Named types
// defined in this package are represented by the builders.
func (td typeDefiner) Define() {
	for _, b := range td.builders {
		def, file := b.def, b.def.File
		base := compileDefinedType(b.ptype, file, td.env, td.tbuilder, td.builders)
		switch tbase := base.(type) {
		case nil:
			continue // keep going to catch  more errors
		case *vdl.Type:
			if tbase == vdl.ErrorType {
				td.env.Errorf(file, def.Pos, "error cannot be renamed")
				continue // keep going to catch more errors
			}
			def.BaseType = tbase
		case vdl.PendingType:
			b.base = tbase
		default:
			panic(fmt.Errorf("vdl: typeDefiner.Define unhandled TypeOrPending %T %v", tbase, tbase))
		}
		b.pending.AssignBase(base)
	}
}

// compileType returns the *vdl.Type corresponding to ptype.  All named types
// referenced by ptype must already be defined.
func compileType(ptype parse.Type, file *File, env *Env) *vdl.Type {
	var tbuilder vdl.TypeBuilder
	typeOrPending := compileLiteralType(ptype, file, env, &tbuilder, nil)
	tbuilder.Build()
	switch top := typeOrPending.(type) {
	case nil:
		return nil
	case *vdl.Type:
		return top
	case vdl.PendingType:
		t, err := top.Built()
		if err != nil {
			env.prefixErrorf(file, ptype.Pos(), err, "invalid type")
			return nil
		}
		return t
	default:
		panic(fmt.Errorf("vdl: compileType unhandled TypeOrPending %T %v", top, top))
	}
}

// compileDefinedType compiles ptype.  It can handle definitions based on array,
// enum, struct and union, as well as definitions based on any literal type.
func compileDefinedType(ptype parse.Type, file *File, env *Env, tbuilder *vdl.TypeBuilder, builders map[string]*typeDefBuilder) vdl.TypeOrPending {
	switch pt := ptype.(type) {
	case *parse.TypeArray:
		elem := compileLiteralType(pt.Elem, file, env, tbuilder, builders)
		if elem == nil {
			return nil
		}
		return tbuilder.Array().AssignLen(pt.Len).AssignElem(elem)
	case *parse.TypeEnum:
		enum := tbuilder.Enum()
		for _, plabel := range pt.Labels {
			enum.AppendLabel(plabel.Name)
		}
		return enum
	case *parse.TypeStruct:
		st := tbuilder.Struct()
		for _, pfield := range pt.Fields {
			ftype := compileLiteralType(pfield.Type, file, env, tbuilder, builders)
			if ftype == nil {
				return nil
			}
			st.AppendField(pfield.Name, ftype)
		}
		return st
	case *parse.TypeUnion:
		union := tbuilder.Union()
		for _, pfield := range pt.Fields {
			ftype := compileLiteralType(pfield.Type, file, env, tbuilder, builders)
			if ftype == nil {
				return nil
			}
			union.AppendField(pfield.Name, ftype)
		}
		return union
	}
	lit := compileLiteralType(ptype, file, env, tbuilder, builders)
	if _, ok := lit.(vdl.PendingOptional); ok {
		// Don't allow Optional at the top-level of a type definition.  The purpose
		// of this rule is twofold:
		// 1) Reduce confusion; the Optional modifier cannot be hidden in a type
		//    definition, it must be explicitly mentioned on each use.
		// 2) The Optional concept is typically translated to pointers in generated
		//    languages, and many languages don't support named pointer types.
		//
		//   type A string            // ok
		//   type B []?string         // ok
		//   type C struct{X ?string} // ok
		//   type D ?string           // bad
		//   type E ?struct{X string} // bad
		env.Errorf(file, ptype.Pos(), "can't define type based on top-level optional")
		return nil
	}
	return lit
}

// compileLiteralType compiles ptype.  It can handle any literal type.  Note
// that array, enum, struct and union are required to be defined and named,
// and aren't allowed as regular literal types.
func compileLiteralType(ptype parse.Type, file *File, env *Env, tbuilder *vdl.TypeBuilder, builders map[string]*typeDefBuilder) vdl.TypeOrPending {
	switch pt := ptype.(type) {
	case *parse.TypeNamed:
		if def, matched := env.ResolveType(pt.Name, file); def != nil {
			if len(matched) < len(pt.Name) {
				env.Errorf(file, pt.Pos(), "type %s invalid (%s unmatched)", pt.Name, pt.Name[len(matched):])
				return nil
			}
			return def.Type
		}
		if b, ok := builders[pt.Name]; ok {
			return b.pending
		}
		env.Errorf(file, pt.Pos(), "type %s undefined", pt.Name)
		return nil
	case *parse.TypeList:
		elem := compileLiteralType(pt.Elem, file, env, tbuilder, builders)
		if elem == nil {
			return nil
		}
		return tbuilder.List().AssignElem(elem)
	case *parse.TypeSet:
		key := compileLiteralType(pt.Key, file, env, tbuilder, builders)
		if key == nil {
			return nil
		}
		return tbuilder.Set().AssignKey(key)
	case *parse.TypeMap:
		key := compileLiteralType(pt.Key, file, env, tbuilder, builders)
		elem := compileLiteralType(pt.Elem, file, env, tbuilder, builders)
		if key == nil || elem == nil {
			return nil
		}
		return tbuilder.Map().AssignKey(key).AssignElem(elem)
	case *parse.TypeOptional:
		elem := compileLiteralType(pt.Base, file, env, tbuilder, builders)
		if elem == nil {
			return nil
		}
		return tbuilder.Optional().AssignElem(elem)
	default:
		env.Errorf(file, pt.Pos(), "unnamed %s type invalid (type must be defined)", ptype.Kind())
		return nil
	}
}

// Build actually builds each type and updates the package with the typedefs.
// The order we call each pending type doesn't matter; the v.io/v23/vdl package
// deals with arbitrary orders, and supports recursive types.  However we want
// the order to be deterministic, otherwise the output will constantly change.
// So we use the same order as the parsed file.
func (td typeDefiner) Build() {
	td.tbuilder.Build()
	for _, pfile := range td.pfiles {
		for _, pdef := range pfile.TypeDefs {
			b := td.builders[pdef.Name]
			def, file := b.def, b.def.File
			if b.base != nil {
				base, err := b.base.Built()
				if err != nil {
					td.env.prefixErrorf(file, b.ptype.Pos(), err, "%s base type invalid", def.Name)
					continue // keep going to catch more errors
				}
				def.BaseType = base
			}
			t, err := b.pending.Built()
			if err != nil {
				td.env.prefixErrorf(file, def.Pos, err, "%s invalid", def.Name)
				continue // keep going to catch more errors
			}
			def.Type = t
			addTypeDef(def, td.env)
		}
	}
	// Make another pass to fill in doc and doc suffix slices for enums, structs
	// and unions.  Typically these are initialized in makeTypeDefBuilder, based
	// on the underlying parse data.  But type definitions based on other named
	// types can't be updated until the base type is actually compiled.
	//
	// TODO(toddw): This doesn't actually attach comments from the base type, it
	// just leaves everything empty.  This is fine for now, but we should revamp
	// the vdl parsing / comment attaching strategy in the future.
	for _, file := range td.pkg.Files {
		for _, def := range file.TypeDefs {
			switch t := def.Type; t.Kind() {
			case vdl.Enum:
				if len(def.LabelDoc) == 0 {
					def.LabelDoc = make([]string, t.NumEnumLabel())
				}
				if len(def.LabelDocSuffix) == 0 {
					def.LabelDocSuffix = make([]string, t.NumEnumLabel())
				}
			case vdl.Struct, vdl.Union:
				if len(def.FieldDoc) == 0 {
					def.FieldDoc = make([]string, t.NumField())
				}
				if len(def.FieldDocSuffix) == 0 {
					def.FieldDocSuffix = make([]string, t.NumField())
				}
			}
		}
	}
}

// addTypeDef updates our various structures to add a new type def.
func addTypeDef(def *TypeDef, env *Env) {
	def.File.TypeDefs = append(def.File.TypeDefs, def)
	def.File.Package.typeDefs[def.Name] = def
	if env != nil {
		// env should only be nil during initialization of the built-in package;
		// NewEnv ensures new environments have the built-in types.
		env.typeDefs[def.Type] = def
	}
}
