// 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
	}
	if td.Build(); !env.Errors.IsEmpty() {
		return
	}
	td.AttachDoc()
	// 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)
					return
				}
				def.BaseType = base
			}
			t, err := b.pending.Built()
			if err != nil {
				td.env.prefixErrorf(file, def.Pos, err, "%s invalid", def.Name)
				return
			}
			def.Type = t
			addTypeDef(def, td.env)
		}
	}
}

// AttachDoc makes 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.
func (td typeDefiner) AttachDoc() {
	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
	}
}
