// 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/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}})
`))
