// 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 "text/template"

// Inputs:
// .pkgName  the Go package name
var headerCode = template.Must(template.New("header").Parse(
	`// Code generated by gocode.Generate; DO NOT EDIT.

package {{.pkgName}}

import (
	"fmt"

	"cuelang.org/go/internal/legacy/cue"
	"cuelang.org/go/encoding/gocode/gocodec"
)

`))

// Inputs:
// .prefix 	  prefix to all generated variable names
// .cueName   name of the top-level CUE value
// .goType    Go type of the receiver or argument
// .zero      zero value of the Go type; nil indicates no value
// .validate  name of the validate function; "" means no validate
// .complete  name of the complete function; "" means no complete
var stubCode = template.Must(template.New("type").Parse(`
var {{.prefix}}val{{.cueName}} = {{.prefix}}Make("{{.cueName}}", {{.zero}})

{{ $sig := .goType | printf "(x %s)" -}}
{{if .validate}}
// {{.validate}}{{if .func}}{{.cueName}}{{end}} validates x.
func {{if .func}}{{.validate}}{{.cueName}}{{$sig}}
     {{- else -}}{{$sig}} {{.validate}}(){{end}} error {
	return {{.prefix}}Codec.Validate({{.prefix}}val{{.cueName}}, x)
}
{{end}}
{{if .complete}}
// {{.complete}}{{if .func}}{{.cueName}}{{end}} completes x.
func {{if .func}}{{.complete}}{{.cueName}}{{$sig}}
     {{- else -}}{{$sig}} {{.complete}}(){{end}} error {
	return {{.prefix}}Codec.Complete({{.prefix}}val{{.cueName}}, x)
}
{{end}}
`))

// Inputs:
// .prefix 	  prefix to all generated variable names
// .runtime   the variable name of a user-supplied runtime, if any
// .data      bytes obtained from Instance.MarshalBinary
var loadCode = template.Must(template.New("load").Parse(`
var {{.prefix}}Codec, {{.prefix}}Instance = func() (*gocodec.Codec, *cue.Instance) {
	var r *cue.Runtime
	r = {{if .runtime}}{{.runtime}}{{else}}&cue.Runtime{}{{end}}
	instances, err := r.Unmarshal({{.prefix}}InstanceData)
	if err != nil {
		panic(err)
	}
	if len(instances) != 1 {
		panic("expected encoding of exactly one instance")
	}
	return gocodec.New(r, nil), instances[0]
}()

// {{.prefix}}Make is called in the init phase to initialize CUE values for
// validation functions.
func {{.prefix}}Make(name string, x interface{}) cue.Value {
	f, err := {{.prefix}}Instance.LookupField(name)
	if err != nil {
		panic(fmt.Errorf("could not find type %q in instance", name))
	}
	v := f.Value
	if x != nil {
		w, err := {{.prefix}}Codec.ExtractType(x)
		if err != nil {
			panic(err)
		}
		v = v.Unify(w)
	}
	return v
}

// Data size: {{len .data}} bytes.
var {{.prefix}}InstanceData = []byte({{printf "%+q" .data}})
`))
