// 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 gogen.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 {
	v := {{.prefix}}Instance.Lookup(name)
	if !v.Exists() {
		panic(fmt.Errorf("could not find type %q in instance", name))
	}
	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}})
`))
