// Code generated by cuelang.org/go/pkg/gen. DO NOT EDIT.

//go:build !bootstrap

package filetypes

import (
	_ "embed"
	"cmp"
	"maps"
	"fmt"
	"slices"

	"cuelang.org/go/cue/build"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
	"cuelang.org/go/internal/filetypes/internal"
	"cuelang.org/go/internal/filetypes/internal/opt"
	"cuelang.org/go/internal/filetypes/internal/genstruct"
)

// TODO use string instead of []byte so that we can
// use the init data directly without copying into
// read-write memory.

//go:embed fileinfo.dat
var fileInfoDataBytes []byte

//go:embed fromfile.dat
var fromFileDataBytes []byte

func init() {
	tagTypes = map[string]TagType{
		{{range $k, $v := .TagTypes}}{{printf "\t%q: %v,\n" $k $v}}{{end}}
	}
}

{{.ToFileParams.GenInit .Generated}}

{{.ToFileResult.GenInit .Generated}}

{{.FromFileParams.GenInit .Generated}}

{{.FromFileResult.GenInit .Generated}}

func toFileGenerated(mode Mode, sc *scope, filename string) (*build.File, errors.Error) {
	key := make([]byte, {{.ToFileParams.Size}})
	{{.ToFileParams.Tags.GenPut "key" "maps.Keys(sc.topLevel)"}}
	{{.ToFileParams.FileExt.GenPut "key" "fileExt(filename)"}}
	{{.ToFileParams.Mode.GenPut "key" "mode"}}

	data, ok := genstruct.FindRecord(fileInfoDataBytes, {{.ToFileParams.Size}}+{{.ToFileResult.Size}}, key)
	if !ok {
		return nil, errors.Newf(token.NoPos, "invalid tag combination")		// TODO what error would be best?
	}

	switch e := {{.ToFileResult.Error.GenGet "data"}}; e {
	default:
		return nil, errors.Newf(token.NoPos, "unknown filetype error %d", e)
	case internal.ErrUnknownFileExtension:
		return nil, errors.Newf(token.NoPos, "unknown file extension %s", fileExt(filename))
	case internal.ErrCouldNotDetermineFileType:
		return nil, errors.Newf(token.NoPos, "could not determine file type for file %q", filename)
	case internal.ErrNoEncodingSpecified:
		return nil, errors.Newf(token.NoPos, "no encoding specified for file %q", filename)
	case 0:
		// no error
	}

	var f build.File
	f.Filename = filename
	f.Encoding = {{.ToFileResult.Encoding.GenGet "data"}}
	f.Interpretation = {{.ToFileResult.Interpretation.GenGet "data"}}
	f.Form = {{.ToFileResult.Form.GenGet "data"}}
	if index := {{.ToFileResult.SubsidiaryTagFuncIndex.GenGet "data"}}; index > 0 {
		tagFunc := subsidiaryTagFuncs[index-1]
		var t subsidiaryTags
		if err := t.unmarshalFromMap(sc.subsidiaryString); err != nil {
			return nil, errors.Promote(err, "")
		}
		t, err := tagFunc(t)
		if err != nil {
			return nil, errors.Promote(err, "")
		}
		f.Tags = t.marshalToMap()

	} else if len(sc.subsidiaryString) > 0 {
		return nil, errors.Newf(token.NoPos, "tag %s is not allowed in this context", someKey(sc.subsidiaryString))
	}
	if index := {{.ToFileResult.SubsidiaryBoolTagFuncIndex.GenGet "data"}}; index > 0 {
		tagFunc := subsidiaryBoolTagFuncs[index-1]
		var t subsidiaryBoolTags
		if err := t.unmarshalFromMap(sc.subsidiaryBool); err != nil {
			return nil, errors.Promote(err, "")
		}
		t, err := tagFunc(t)
		if err != nil {
			return nil, errors.Promote(err, "")
		}
		f.BoolTags = t.marshalToMap()
	} else if len(sc.subsidiaryBool) > 0 {
		return nil, errors.Newf(token.NoPos, "tag %s is not allowed in this context", someKey(sc.subsidiaryBool))
	}

	return &f, nil
}

func fromFileGenerated(b *build.File, mode Mode) (*FileInfo, error) {
	key := make([]byte, {{.FromFileParams.Size}})
	{{.FromFileParams.Mode.GenPut "key" "mode"}}
	{{.FromFileParams.Encoding.GenPut "key" "b.Encoding"}}
	{{.FromFileParams.Interpretation.GenPut "key" "b.Interpretation"}}
	{{.FromFileParams.Form.GenPut "key" "b.Form"}}

	data, ok := genstruct.FindRecord(fromFileDataBytes, {{.FromFileParams.Size}}+{{.FromFileResult.Size}}, key)
	if !ok {
		return nil, errors.Newf(token.NoPos, "no encoding specified")
	}
	fi := &FileInfo{
		Filename: b.Filename,
		Encoding: {{.FromFileResult.Encoding.GenGet "data"}},
		Interpretation: {{.FromFileResult.Interpretation.GenGet "data"}},
		Form: {{.FromFileResult.Form.GenGet "data"}},
	}
	fi.SetAspects({{.FromFileResult.Aspects.GenGet "data"}})
	return fi, nil
}

func someKey[K cmp.Ordered, V any](m map[K] V) K {
	return slices.Sorted(maps.Keys(m))[0]
}

var subsidiaryBoolTagFuncs = []func(subsidiaryBoolTags) (subsidiaryBoolTags, error) {
{{range .SubsidiaryBoolTagFuncCount}}unifySubsidiaryBoolTags_{{.}},
{{end}}
}

var subsidiaryTagFuncs = []func(subsidiaryTags) (subsidiaryTags, error) {
{{range .SubsidiaryTagFuncCount}}unifySubsidiaryTags_{{.}},
{{end}}
}
