// Copyright 2019 CUE Authors
//
// 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 gocode

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/types"
	"text/template"

	"golang.org/x/tools/go/packages"

	"cuelang.org/go/cue/errors"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/legacy/cue"
)

// Config defines options for generation Go code.
type Config struct {
	// Prefix is used as a prefix to all generated variables. It defaults to
	// cuegen.
	Prefix string

	// ValidateName defines the default name for validation methods or prefix
	// for validation functions. The default is "Validate". Set to "-" to
	// disable generating validators.
	ValidateName string

	// CompleteName defines the default name for complete methods or prefix
	// for complete functions. The default is "-" (disabled).
	CompleteName string

	// The cue.Runtime variable name to use for initializing Codecs.
	// A new Runtime is created by default.
	RuntimeVar string
}

const defaultPrefix = "cuegen"

// Generate generates Go code for the given instance in the directory of the
// given package.
//
// Generate converts top-level declarations to corresponding Go code. By default,
// it will only generate validation functions of methods for exported top-level
// declarations. The behavior can be altered with the @go attribute.
//
// The go attribute has the following form @go(<name>{,<option>}), where option
// is either a key-value pair or a flag. The name maps the CUE name to an
// alternative Go name. The special value '-' is used to indicate the field
// should be ignored for any Go generation.
//
// The following options are supported:
//
//     type=<gotype>    The Go type as which this value should be interpreted.
//                      This defaults to the type with the (possibly overridden)
//                      name of the field.
//     validate=<name>  Alternative name for the validation function or method
//                      Setting this to the empty string disables generation.
//     complete=<name>  Alternative name for the validation function or method.
//                      Setting this to the empty string disables generation.
//     func             Generate as a function instead of a method.
//
//
// Selection and Naming
//
// Generate will not generate any code for fields that have no go attribute
// and that are not exported or for which there is no namesake Go type.
// If the go attribute has the special value '-' as its name it wil be dropped
// as well. In all other cases Generate will generate Go code, even if the
// resulting code will not compile. For instance, Generate will generate Go
// code even if the user defines a Go type in the attribute that does not
// exist.
//
// If a field selected for generation and the go name matches that the name of
// the Go type, the corresponding validate and complete code are generated as
// methods by default. If not, it will be generated as a function. The default
// function name is the default operation name with the Go name as a suffix.
//
//
// Caveats
// Currently not supported:
//   - option to generate Go structs (or automatically generate if undefined)
//   - for type option to refer to types outside the package.
//
func Generate(pkgPath string, inst *cue.Instance, c *Config) (b []byte, err error) {
	// TODO: if inst is nil, the instance is loaded from CUE files in the same
	// package directory with the same package name.
	if err = inst.Value().Validate(); err != nil {
		return nil, err
	}
	if c == nil {
		c = &Config{}
	}
	g := &generator{
		Config: *c,

		typeMap: map[string]types.Type{},
	}

	pkgName := inst.PkgName

	if pkgPath != "" {
		loadCfg := &packages.Config{
			Mode: packages.LoadAllSyntax,
		}
		pkgs, err := packages.Load(loadCfg, pkgPath)
		if err != nil {
			return nil, fmt.Errorf("generating failed: %v", err)
		}

		if len(pkgs) != 1 {
			return nil, fmt.Errorf(
				"generate only allowed for one package at a time, found %d",
				len(pkgs))
		}

		g.pkg = pkgs[0]
		if len(g.pkg.Errors) > 0 {
			for _, err := range g.pkg.Errors {
				g.addErr(err)
			}
			return nil, g.err
		}

		pkgName = g.pkg.Name

		for _, obj := range g.pkg.TypesInfo.Defs {
			if obj == nil || obj.Pkg() != g.pkg.Types || obj.Parent() == nil {
				continue
			}
			g.typeMap[obj.Name()] = obj.Type()
		}
	}

	// TODO: add package doc if there is no existing Go package or if it doesn't
	// have package documentation already.
	g.exec(headerCode, map[string]string{
		"pkgName": pkgName,
	})

	iter, err := inst.Value().Fields(cue.Definitions(true))
	g.addErr(err)

	for iter.Next() {
		g.decl(iter.Label(), iter.Value())
	}

	r := internal.GetRuntimeNew(inst).(*cue.Runtime)
	b, err = r.Marshal(inst)
	g.addErr(err)

	g.exec(loadCode, map[string]string{
		"runtime": g.RuntimeVar,
		"prefix":  strValue(g.Prefix, defaultPrefix),
		"data":    string(b),
	})

	if g.err != nil {
		return nil, g.err
	}

	b, err = format.Source(g.w.Bytes())
	if err != nil {
		// Return bytes as well to allow analysis of the failed Go code.
		return g.w.Bytes(), err
	}

	return b, err
}

type generator struct {
	Config
	pkg     *packages.Package
	typeMap map[string]types.Type

	w   bytes.Buffer
	err errors.Error
}

func (g *generator) addErr(err error) {
	if err != nil {
		g.err = errors.Append(g.err, errors.Promote(err, "generate failed"))
	}
}

func (g *generator) exec(t *template.Template, data interface{}) {
	g.addErr(t.Execute(&g.w, data))
}

func (g *generator) decl(name string, v cue.Value) {
	attr := v.Attribute("go")

	if !ast.IsExported(name) && attr.Err() != nil {
		return
	}

	goName := name
	switch s, _ := attr.String(0); s {
	case "":
	case "-":
		return
	default:
		goName = s
	}

	goTypeName := goName
	goType := ""
	if str, ok, _ := attr.Lookup(1, "type"); ok {
		goType = str
		goTypeName = str
	}

	isFunc, _ := attr.Flag(1, "func")
	if goTypeName != goName {
		isFunc = true
	}

	zero := "nil"

	typ, ok := g.typeMap[goTypeName]
	if !ok && !mappedGoTypes(goTypeName) {
		return
	}
	if goType == "" {
		goType = goTypeName
		if typ != nil {
			switch typ.Underlying().(type) {
			case *types.Struct, *types.Array:
				goType = "*" + goTypeName
				zero = fmt.Sprintf("&%s{}", goTypeName)
			case *types.Pointer:
				zero = fmt.Sprintf("%s(nil)", goTypeName)
				isFunc = true
			}
		}
	}

	g.exec(stubCode, map[string]interface{}{
		"prefix":  strValue(g.Prefix, defaultPrefix),
		"cueName": name,   // the field name of the CUE type
		"goType":  goType, // the receiver or argument type
		"zero":    zero,   // the zero value of the underlying type

		// @go attribute options
		"func":     isFunc,
		"validate": lookupName(attr, "validate", strValue(g.ValidateName, "Validate")),
		"complete": lookupName(attr, "complete", g.CompleteName),
	})
}

func lookupName(attr cue.Attribute, option, config string) string {
	name, ok, _ := attr.Lookup(1, option)
	if !ok {
		name = config
	}
	if name == "-" {
		return ""
	}
	return name
}

func strValue(have, fallback string) string {
	if have == "" {
		return fallback
	}
	return have
}

func mappedGoTypes(s string) bool {
	switch s {
	case "bool", "float32", "float64",
		"int", "int8", "int16", "int32", "int64", "string",
		"uint", "uint8", "uint16", "uint32", "uint64":
		return true
	}
	return false
}
