// 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 openapi

import (
	"fmt"
	"math"
	"path"
	"regexp"
	"sort"
	"strconv"
	"strings"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
)

type buildContext struct {
	inst      *cue.Instance
	refPrefix string
	path      []string

	expandRefs  bool
	structural  bool
	nameFunc    func(inst *cue.Instance, path []string) string
	descFunc    func(v cue.Value) string
	fieldFilter *regexp.Regexp
	evalDepth   int // detect cycles when resolving references

	schemas *OrderedMap

	// Track external schemas.
	externalRefs map[string]*externalType
}

type externalType struct {
	ref   string
	inst  *cue.Instance
	path  []string
	value cue.Value
}

type oaSchema = OrderedMap

type typeFunc func(b *builder, a cue.Value)

func schemas(g *Generator, inst *cue.Instance) (schemas *ast.StructLit, err error) {
	var fieldFilter *regexp.Regexp
	if g.FieldFilter != "" {
		fieldFilter, err = regexp.Compile(g.FieldFilter)
		if err != nil {
			return nil, errors.Newf(token.NoPos, "invalid field filter: %v", err)
		}

		// verify that certain elements are still passed.
		for _, f := range strings.Split(
			"version,title,allOf,anyOf,not,enum,Schema/properties,Schema/items"+
				"nullable,type", ",") {
			if fieldFilter.MatchString(f) {
				return nil, errors.Newf(token.NoPos, "field filter may not exclude %q", f)
			}
		}
	}

	c := buildContext{
		inst:         inst,
		refPrefix:    "components/schemas",
		expandRefs:   g.ExpandReferences,
		structural:   g.ExpandReferences,
		nameFunc:     g.ReferenceFunc,
		descFunc:     g.DescriptionFunc,
		schemas:      &OrderedMap{},
		externalRefs: map[string]*externalType{},
		fieldFilter:  fieldFilter,
	}

	defer func() {
		switch x := recover().(type) {
		case nil:
		case *openapiError:
			err = x
		default:
			panic(x)
		}
	}()

	// Although paths is empty for now, it makes it valid OpenAPI spec.

	i, err := inst.Value().Fields(cue.Definitions(true))
	if err != nil {
		return nil, err
	}
	for i.Next() {
		// message, enum, or constant.
		label := i.Label()
		if c.isInternal(label) {
			continue
		}
		ref := c.makeRef(inst, []string{label})
		if ref == "" {
			continue
		}
		c.schemas.Set(ref, c.build(label, i.Value()))
	}

	// keep looping until a fixed point is reached.
	for done := 0; len(c.externalRefs) != done; {
		done = len(c.externalRefs)

		// From now on, all references need to be expanded
		external := []string{}
		for k := range c.externalRefs {
			external = append(external, k)
		}
		sort.Strings(external)

		for _, k := range external {
			ext := c.externalRefs[k]
			c.schemas.Set(ext.ref, c.build(ext.ref, ext.value.Eval()))
		}
	}

	return (*ast.StructLit)(c.schemas), nil
}

func (c *buildContext) build(name string, v cue.Value) *ast.StructLit {
	return newCoreBuilder(c).schema(nil, name, v)
}

// isInternal reports whether or not to include this type.
func (c *buildContext) isInternal(name string) bool {
	// TODO: allow a regexp filter in Config. If we have closed structs and
	// definitions, this will likely be unnecessary.
	return strings.HasSuffix(name, "_value")
}

func (b *builder) failf(v cue.Value, format string, args ...interface{}) {
	panic(&openapiError{
		errors.NewMessage(format, args),
		b.ctx.path,
		v.Pos(),
	})
}

func (b *builder) unsupported(v cue.Value) {
	if b.format == "" {
		// Not strictly an error, but consider listing it as a warning
		// in strict mode.
	}
}

func (b *builder) checkArgs(a []cue.Value, n int) {
	if len(a)-1 != n {
		b.failf(a[0], "%v must be used with %d arguments", a[0], len(a)-1)
	}
}

func (b *builder) schema(core *builder, name string, v cue.Value) *ast.StructLit {
	oldPath := b.ctx.path
	b.ctx.path = append(b.ctx.path, name)
	defer func() { b.ctx.path = oldPath }()

	var c *builder
	if core == nil && b.ctx.structural {
		c = newCoreBuilder(b.ctx)
		c.buildCore(v)     // initialize core structure
		c.coreSchema(name) // build the
	} else {
		c = newRootBuilder(b.ctx)
		c.core = core
	}

	return c.fillSchema(v)
}

func (b *builder) getDoc(v cue.Value) {
	doc := []string{}
	if b.ctx.descFunc != nil {
		if str := b.ctx.descFunc(v); str != "" {
			doc = append(doc, str)
		}
	} else {
		for _, d := range v.Doc() {
			doc = append(doc, d.Text())
		}
	}
	if len(doc) > 0 {
		str := strings.TrimSpace(strings.Join(doc, "\n\n"))
		b.setSingle("description", ast.NewString(str), true)
	}
}

func (b *builder) fillSchema(v cue.Value) *ast.StructLit {
	if b.filled != nil {
		return b.filled
	}

	b.setValueType(v)
	b.format = extractFormat(v)
	b.deprecated = getDeprecated(v)

	if b.core == nil || len(b.core.values) > 1 {
		isRef := b.value(v, nil)
		if isRef {
			b.typ = ""
		}

		if !isRef && !b.ctx.structural {
			b.getDoc(v)
		}
	}

	schema := b.finish()
	s := (*ast.StructLit)(schema)

	simplify(b, s)

	sortSchema(s)

	b.filled = s
	return s
}

func label(d ast.Decl) string {
	f := d.(*ast.Field)
	s, _, _ := ast.LabelName(f.Label)
	return s
}

func value(d ast.Decl) ast.Expr {
	return d.(*ast.Field).Value
}

func sortSchema(s *ast.StructLit) {
	sort.Slice(s.Elts, func(i, j int) bool {
		iName := label(s.Elts[i])
		jName := label(s.Elts[j])
		pi := fieldOrder[iName]
		pj := fieldOrder[jName]
		if pi != pj {
			return pi > pj
		}
		return iName < jName
	})
}

var fieldOrder = map[string]int{
	"description":      31,
	"type":             30,
	"format":           29,
	"required":         28,
	"properties":       27,
	"minProperties":    26,
	"maxProperties":    25,
	"minimum":          24,
	"exclusiveMinimum": 23,
	"maximum":          22,
	"exclusiveMaximum": 21,
	"minItems":         18,
	"maxItems":         17,
	"minLength":        16,
	"maxLength":        15,
	"items":            14,
	"enum":             13,
	"default":          12,
}

func (b *builder) resolve(v cue.Value) cue.Value {
	// Cycles are not allowed when expanding references. Right now we just
	// cap the depth of evaluation at 30.
	// TODO: do something more principled.
	const maxDepth = 30
	if b.ctx.evalDepth > maxDepth {
		b.failf(v, "maximum stack depth of %d reached", maxDepth)
	}
	b.ctx.evalDepth++
	defer func() { b.ctx.evalDepth-- }()

	switch op, a := v.Expr(); op {
	case cue.SelectorOp:
		field, _ := a[1].String()
		f, _ := b.resolve(a[0]).LookupField(field)
		v = cue.Value{}
		if !f.IsOptional {
			v = f.Value
		}
	}
	return v
}

func (b *builder) value(v cue.Value, f typeFunc) (isRef bool) {
	count := 0
	disallowDefault := false
	var values cue.Value
	if b.ctx.expandRefs || b.format != "" {
		values = b.resolve(v)
		count = 1
	} else {
		dedup := map[string]bool{}
		hasNoRef := false
		for _, v := range appendSplit(nil, cue.AndOp, v) {
			// This may be a reference to an enum. So we need to check references before
			// dissecting them.
			switch p, r := v.Reference(); {
			case len(r) > 0:
				ref := b.ctx.makeRef(p, r)
				if ref == "" {
					v = b.resolve(v)
					break
				}
				if dedup[ref] {
					continue
				}
				dedup[ref] = true

				b.addRef(v, p, r)
				disallowDefault = true
				continue
			}
			hasNoRef = true
			count++
			values = values.Unify(v)
		}
		isRef = !hasNoRef && len(dedup) == 1
	}

	if count > 0 { // TODO: implement IsAny.
		// NOTE: Eval is not necessary here. Removing it will yield
		// different results that also are correct. The difference is that
		// Eval detects and eliminates impossible combinations at the
		// expense of having potentially much larger configurations due to
		// a combinatorial explosion. This rudimentary check picks the least
		// fo the two extreme forms.
		if eval := values.Eval(); countNodes(eval) < countNodes(values) {
			values = eval
		}

		for _, v := range appendSplit(nil, cue.AndOp, values) {
			switch {
			case isConcrete(v):
				b.dispatch(f, v)
				if !b.isNonCore() {
					b.set("enum", ast.NewList(b.decode(v)))
				}
			default:
				if a := appendSplit(nil, cue.OrOp, v); len(a) > 1 {
					b.disjunction(a, f)
				} else {
					v = a[0]
					if err := v.Err(); err != nil {
						b.failf(v, "openapi: %v", err)
						return
					}
					b.dispatch(f, v)
				}
			}
		}
	}

	if v, ok := v.Default(); ok && v.IsConcrete() && !disallowDefault {
		// TODO: should we show the empty list default? This would be correct
		// but perhaps a bit too pedantic and noisy.
		switch {
		case v.Kind() == cue.ListKind:
			iter, _ := v.List()
			if !iter.Next() {
				// Don't show default for empty list.
				break
			}
			fallthrough
		default:
			if !b.isNonCore() {
				e := v.Syntax().(ast.Expr)
				b.setFilter("Schema", "default", e)
			}
		}
	}
	return isRef
}

func appendSplit(a []cue.Value, splitBy cue.Op, v cue.Value) []cue.Value {
	op, args := v.Expr()
	if op == cue.NoOp && len(args) > 0 {
		// TODO: this is to deal with default value removal. This may change
		// whe we completely separate default values from values.
		a = append(a, args...)
	} else if op != splitBy {
		a = append(a, v)
	} else {
		for _, v := range args {
			a = appendSplit(a, splitBy, v)
		}
	}
	return a
}

func countNodes(v cue.Value) (n int) {
	switch op, a := v.Expr(); op {
	case cue.OrOp, cue.AndOp:
		for _, v := range a {
			n += countNodes(v)
		}
		n += len(a) - 1
	default:
		switch v.Kind() {
		case cue.ListKind:
			for i, _ := v.List(); i.Next(); {
				n += countNodes(i.Value())
			}
		case cue.StructKind:
			for i, _ := v.Fields(); i.Next(); {
				n += countNodes(i.Value()) + 1
			}
		}
	}
	return n + 1
}

// isConcrete reports whether v is concrete and not a struct (recursively).
// structs are not supported as the result of a struct enum depends on how
// conjunctions and disjunctions are distributed. We could consider still doing
// this if we define a normal form.
func isConcrete(v cue.Value) bool {
	if !v.IsConcrete() {
		return false
	}
	if v.Kind() == cue.StructKind {
		return false // TODO: handle struct kinds
	}
	for list, _ := v.List(); list.Next(); {
		if !isConcrete(list.Value()) {
			return false
		}
	}
	return true
}

func (b *builder) disjunction(a []cue.Value, f typeFunc) {
	disjuncts := []cue.Value{}
	enums := []ast.Expr{} // TODO: unique the enums
	nullable := false     // Only supported in OpenAPI, not JSON schema

	for _, v := range a {
		switch {
		case v.Null() == nil:
			// TODO: for JSON schema, we need to fall through.
			nullable = true

		case isConcrete(v):
			enums = append(enums, b.decode(v))

		default:
			disjuncts = append(disjuncts, v)
		}
	}

	// Only one conjunct?
	if len(disjuncts) == 0 || (len(disjuncts) == 1 && len(enums) == 0) {
		if len(disjuncts) == 1 {
			b.value(disjuncts[0], f)
		}
		if len(enums) > 0 && !b.isNonCore() {
			b.set("enum", ast.NewList(enums...))
		}
		if nullable {
			b.setSingle("nullable", ast.NewBool(true), true) // allowed in Structural
		}
		return
	}

	anyOf := []ast.Expr{}
	if len(enums) > 0 {
		anyOf = append(anyOf, b.kv("enum", ast.NewList(enums...)))
	}

	hasAny := false
	for _, v := range disjuncts {
		c := newOASBuilder(b)
		c.value(v, f)
		t := c.finish()
		if len(t.Elts) == 0 {
			if c.typ == "" {
				hasAny = true
			}
			continue
		}
		anyOf = append(anyOf, (*ast.StructLit)(t))
	}

	// If any of the types was "any", a oneOf may be discarded.
	if !hasAny {
		// TODO: analyze CUE structs to figure out if it should be oneOf or
		// anyOf. More precisely, if non of the elements subsume each other,
		// it is oneOf, if some do, it is anyOf. For closed structs, the
		// structure needs to be oneOf(X, not(anyOf(X))).
		// As the source is protobuf for now, it is always the latter form.
		b.set("oneOf", ast.NewList(
			append(anyOf,
				ast.NewStruct("not",
					ast.NewStruct("anyOf", ast.NewList(anyOf...))))...))
	}

	if nullable {
		b.setSingle("nullable", ast.NewBool(true), true)
	}
}

func (b *builder) setValueType(v cue.Value) {
	if b.core != nil {
		return
	}

	switch v.IncompleteKind() {
	case cue.BoolKind:
		b.typ = "boolean"
	case cue.FloatKind, cue.NumberKind:
		b.typ = "number"
	case cue.IntKind:
		b.typ = "integer"
	case cue.BytesKind:
		b.typ = "string"
	case cue.StringKind:
		b.typ = "string"
	case cue.StructKind:
		b.typ = "object"
	case cue.ListKind:
		b.typ = "array"
	}
}

func (b *builder) dispatch(f typeFunc, v cue.Value) {
	if f != nil {
		f(b, v)
		return
	}

	switch v.IncompleteKind() {
	case cue.NullKind:
		// TODO: for JSON schema we would set the type here. For OpenAPI,
		// it must be nullable.
		b.setSingle("nullable", ast.NewBool(true), true)

	case cue.BoolKind:
		b.setType("boolean", "")
		// No need to call.

	case cue.FloatKind, cue.NumberKind:
		// TODO:
		// Common   Name	type	format	Comments
		// float	number	float
		// double	number	double
		b.setType("number", "") // may be overridden to integer
		b.number(v)

	case cue.IntKind:
		// integer	integer	int32	signed 	32 bits
		// long		integer	int64	signed 	64 bits
		b.setType("integer", "") // may be overridden to integer
		b.number(v)

		// TODO: for JSON schema, consider adding multipleOf: 1.

	case cue.BytesKind:
		// byte		string	byte	base64 	encoded characters
		// binary	string	binary	any 	sequence of octets
		b.setType("string", "byte")
		b.bytes(v)
	case cue.StringKind:
		// date		string			date	   As defined by full-date - RFC3339
		// dateTime	string			date-time  As defined by date-time - RFC3339
		// password	string			password   A hint to UIs to obscure input
		b.setType("string", "")
		b.string(v)
	case cue.StructKind:
		b.setType("object", "")
		b.object(v)
	case cue.ListKind:
		b.setType("array", "")
		b.array(v)
	}
}

// object supports the following
// - maxProperties: maximum allowed fields in this struct.
// - minProperties: minimum required fields in this struct.
// - patternProperties: [regexp]: schema
//   TODO: we can support this once .kv(key, value) allow
//      foo [=~"pattern"]: type
//      An instance field must match all schemas for which a regexp matches.
//   Even though it is not supported in OpenAPI, we should still accept it
//   when receiving from OpenAPI. We could possibly use disjunctions to encode
//   this.
// - dependencies: what?
// - propertyNames: schema
//   every property name in the enclosed schema matches that of
func (b *builder) object(v cue.Value) {
	// TODO: discriminator objects: we could theoretically derive discriminator
	// objects automatically: for every object in a oneOf/allOf/anyOf, or any
	// object composed of the same type, if a property is required and set to a
	// constant value for each type, it is a discriminator.

	switch op, a := v.Expr(); op {
	case cue.CallOp:
		name := fmt.Sprint(a[0])
		switch name {
		case "struct.MinFields":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "minProperties", b.int(a[1]))
			return

		case "struct.MaxFields":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "maxProperties", b.int(a[1]))
			return

		default:
			b.unsupported(a[0])
			return
		}

	case cue.NoOp:
		// TODO: extract format from specific type.

	default:
		b.failf(v, "unsupported op %v for object type (%v)", op, v)
		return
	}

	required := []ast.Expr{}
	for i, _ := v.Fields(); i.Next(); {
		required = append(required, ast.NewString(i.Label()))
	}
	if len(required) > 0 {
		b.setFilter("Schema", "required", ast.NewList(required...))
	}

	var properties *OrderedMap
	if b.singleFields != nil {
		properties = b.singleFields.getMap("properties")
	}
	hasProps := properties != nil
	if !hasProps {
		properties = &OrderedMap{}
	}

	for i, _ := v.Fields(cue.Optional(true)); i.Next(); {
		label := i.Label()
		var core *builder
		if b.core != nil {
			core = b.core.properties[label]
		}
		schema := b.schema(core, label, i.Value())
		if !b.isNonCore() || len(schema.Elts) > 0 {
			properties.Set(label, schema)
		}
	}

	if !hasProps && properties.len() > 0 {
		b.setSingle("properties", (*ast.StructLit)(properties), false)
	}

	if t, ok := v.Elem(); ok && (b.core == nil || b.core.items == nil) {
		schema := b.schema(nil, "*", t)
		if len(schema.Elts) > 0 {
			b.setSingle("additionalProperties", schema, true) // Not allowed in structural.
		}
	}

	// TODO: maxProperties, minProperties: can be done once we allow cap to
	// unify with structs.
}

// List constraints:
//
// Max and min items.
// - maxItems: int (inclusive)
// - minItems: int (inclusive)
// - items (item type)
//   schema: applies to all items
//   array of schemas:
//       schema at pos must match if both value and items are defined.
// - additional items:
//   schema: where items must be an array of schemas, intstance elements
//   succeed for if they match this value for any value at a position
//   greater than that covered by items.
// - uniqueItems: bool
//   TODO: support with list.Unique() unique() or comprehensions.
//   For the latter, we need equality for all values, which is doable,
//   but not done yet.
//
// NOT SUPPORTED IN OpenAPI:
// - contains:
//   schema: an array instance is valid if at least one element matches
//   this schema.
func (b *builder) array(v cue.Value) {

	switch op, a := v.Expr(); op {
	case cue.CallOp:
		name := fmt.Sprint(a[0])
		switch name {
		case "list.UniqueItems":
			b.checkArgs(a, 0)
			b.setFilter("Schema", "uniqueItems", ast.NewBool(true))
			return

		case "list.MinItems":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "minItems", b.int(a[1]))
			return

		case "list.MaxItems":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "maxItems", b.int(a[1]))
			return

		default:
			b.unsupported(a[0])
			return
		}

	case cue.NoOp:
		// TODO: extract format from specific type.

	default:
		b.failf(v, "unsupported op %v for array type", op)
		return
	}

	// Possible conjuncts:
	//   - one list (CUE guarantees merging all conjuncts)
	//   - no cap: is unified with list
	//   - unique items: at most one, but idempotent if multiple.
	// There is never a need for allOf or anyOf. Note that a CUE list
	// corresponds almost one-to-one to OpenAPI lists.
	items := []ast.Expr{}
	count := 0
	for i, _ := v.List(); i.Next(); count++ {
		items = append(items, b.schema(nil, strconv.Itoa(count), i.Value()))
	}
	if len(items) > 0 {
		// TODO: per-item schema are not allowed in OpenAPI, only in JSON Schema.
		// Perhaps we should turn this into an OR after first normalizing
		// the entries.
		b.set("items", ast.NewList(items...))
		// panic("per-item types not supported in OpenAPI")
	}

	// TODO:
	// A CUE cap can be a set of discontinuous ranges. If we encounter this,
	// we can create an allOf(list type, anyOf(ranges)).
	cap := v.Len()
	hasMax := false
	maxLength := int64(math.MaxInt64)

	if n, capErr := cap.Int64(); capErr == nil {
		maxLength = n
		hasMax = true
	} else {
		b.value(cap, (*builder).listCap)
	}

	if !hasMax || int64(len(items)) < maxLength {
		if typ, ok := v.Elem(); ok {
			var core *builder
			if b.core != nil {
				core = b.core.items
			}
			t := b.schema(core, "*", typ)
			if len(items) > 0 {
				b.setFilter("Schema", "additionalItems", t) // Not allowed in structural.
			} else if !b.isNonCore() || len(t.Elts) > 0 {
				b.setSingle("items", t, true)
			}
		}
	}
}

func (b *builder) listCap(v cue.Value) {
	switch op, a := v.Expr(); op {
	case cue.LessThanOp:
		b.setFilter("Schema", "maxItems", b.inta(a[0], -1))
	case cue.LessThanEqualOp:
		b.setFilter("Schema", "maxItems", b.inta(a[0], 0))
	case cue.GreaterThanOp:
		b.setFilter("Schema", "minItems", b.inta(a[0], 1))
	case cue.GreaterThanEqualOp:
		if b.int64(a[0]) > 0 {
			b.setFilter("Schema", "minItems", b.inta(a[0], 0))
		}
	case cue.NoOp:
		// must be type, so okay.
	case cue.NotEqualOp:
		i := b.int(a[0])
		b.setNot("allOff", ast.NewList(
			b.kv("minItems", i),
			b.kv("maxItems", i),
		))

	default:
		b.failf(v, "unsupported op for list capacity %v", op)
		return
	}
}

func (b *builder) number(v cue.Value) {
	// Multiple conjuncts mostly means just additive constraints.
	// Type may be number of float.

	switch op, a := v.Expr(); op {
	case cue.LessThanOp:
		b.setFilter("Schema", "exclusiveMaximum", b.big(a[0]))

	case cue.LessThanEqualOp:
		b.setFilter("Schema", "maximum", b.big(a[0]))

	case cue.GreaterThanOp:
		b.setFilter("Schema", "exclusiveMinimum", b.big(a[0]))

	case cue.GreaterThanEqualOp:
		b.setFilter("Schema", "minimum", b.big(a[0]))

	case cue.NotEqualOp:
		i := b.big(a[0])
		b.setNot("allOff", ast.NewList(
			b.kv("minimum", i),
			b.kv("maximum", i),
		))

	case cue.CallOp:
		name := fmt.Sprint(a[0])
		switch name {
		case "math.MultipleOf":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "multipleOf", b.int(a[1]))

		default:
			b.unsupported(a[0])
			return
		}

	case cue.NoOp:
		// TODO: extract format from specific type.

	default:
		b.failf(v, "unsupported op for number %v", op)
	}
}

// Multiple Regexp conjuncts are represented as allOf all other
// constraints can be combined unless in the even of discontinuous
// lengths.

// string supports the following options:
//
// - maxLength (Unicode codepoints)
// - minLength (Unicode codepoints)
// - pattern (a regexp)
//
// The regexp pattern is as follows, and is limited to be a  strict subset of RE2:
// Ref: https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-3.3
//
// JSON schema requires ECMA 262 regular expressions, but
// limited to the following constructs:
//   - simple character classes: [abc]
//   - range character classes: [a-z]
//   - complement character classes: [^abc], [^a-z]
//   - simple quantifiers: +, *, ?, and lazy versions +? *? ??
//   - range quantifiers: {x}, {x,y}, {x,}, {x}?, {x,y}?, {x,}?
//   - begin and end anchors: ^ and $
//   - simple grouping: (...)
//   - alteration: |
// This is a subset of RE2 used by CUE.
//
// Most notably absent:
//   - the '.' for any character (not sure if that is a doc bug)
//   - character classes \d \D [[::]] \pN \p{Name} \PN \P{Name}
//   - word boundaries
//   - capturing directives.
//   - flag setting
//   - comments
//
// The capturing directives and comments can be removed without
// compromising the meaning of the regexp (TODO). Removing
// flag setting will be tricky. Unicode character classes,
// boundaries, etc can be compiled into simple character classes,
// although the resulting regexp will look cumbersome.
//
func (b *builder) string(v cue.Value) {
	switch op, a := v.Expr(); op {

	case cue.RegexMatchOp, cue.NotRegexMatchOp:
		s, err := a[0].String()
		if err != nil {
			// TODO: this may be an unresolved interpolation or expression. Consider
			// whether it is reasonable to treat unevaluated operands as wholes and
			// generate a compound regular expression.
			b.failf(v, "regexp value must be a string: %v", err)
			return
		}
		if op == cue.RegexMatchOp {
			b.setFilter("Schema", "pattern", ast.NewString(s))
		} else {
			b.setNot("pattern", ast.NewString(s))
		}

	case cue.NoOp, cue.SelectorOp:

	case cue.CallOp:
		name := fmt.Sprint(a[0])
		switch name {
		case "strings.MinRunes":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "minLength", b.int(a[1]))
			return

		case "strings.MaxRunes":
			b.checkArgs(a, 1)
			b.setFilter("Schema", "maxLength", b.int(a[1]))
			return

		default:
			b.unsupported(a[0])
			return
		}

	default:
		b.failf(v, "unsupported op %v for string type", op)
	}
}

func (b *builder) bytes(v cue.Value) {
	switch op, a := v.Expr(); op {

	case cue.RegexMatchOp, cue.NotRegexMatchOp:
		s, err := a[0].Bytes()
		if err != nil {
			// TODO: this may be an unresolved interpolation or expression. Consider
			// whether it is reasonable to treat unevaluated operands as wholes and
			// generate a compound regular expression.
			b.failf(v, "regexp value must be of type bytes: %v", err)
			return
		}

		e := ast.NewString(string(s))
		if op == cue.RegexMatchOp {
			b.setFilter("Schema", "pattern", e)
		} else {
			b.setNot("pattern", e)
		}

		// TODO: support the following JSON schema constraints
		// - maxLength
		// - minLength

	case cue.NoOp, cue.SelectorOp:

	default:
		b.failf(v, "unsupported op %v for bytes type", op)
	}
}

type builder struct {
	ctx          *buildContext
	typ          string
	format       string
	singleFields *oaSchema
	current      *oaSchema
	allOf        []*ast.StructLit
	deprecated   bool

	// Building structural schema
	core       *builder
	kind       cue.Kind
	filled     *ast.StructLit
	values     []cue.Value // in structural mode, all values of not and *Of.
	keys       []string
	properties map[string]*builder
	items      *builder
}

func newRootBuilder(c *buildContext) *builder {
	return &builder{ctx: c}
}

func newOASBuilder(parent *builder) *builder {
	core := parent
	if parent.core != nil {
		core = parent.core
	}
	b := &builder{
		core:   core,
		ctx:    parent.ctx,
		typ:    parent.typ,
		format: parent.format,
	}
	return b
}

func (b *builder) isNonCore() bool {
	return b.core != nil
}

func (b *builder) setType(t, format string) {
	if b.typ == "" {
		b.typ = t
		if format != "" {
			b.format = format
		}
	}
}

func setType(t *oaSchema, b *builder) {
	if b.typ != "" {
		if b.core == nil || (b.core.typ != b.typ && !b.ctx.structural) {
			if !t.exists("type") {
				t.Set("type", ast.NewString(b.typ))
			}
		}
	}
	if b.format != "" {
		if b.core == nil || b.core.format != b.format {
			t.Set("format", ast.NewString(b.format))
		}
	}
}

// setFilter is like set, but allows the key-value pair to be filtered.
func (b *builder) setFilter(schema, key string, v ast.Expr) {
	if re := b.ctx.fieldFilter; re != nil && re.MatchString(path.Join(schema, key)) {
		return
	}
	b.set(key, v)
}

// setSingle sets a value of which there should only be one.
func (b *builder) setSingle(key string, v ast.Expr, drop bool) {
	if b.singleFields == nil {
		b.singleFields = &OrderedMap{}
	}
	if b.singleFields.exists(key) {
		if !drop {
			b.failf(cue.Value{}, "more than one value added for key %q", key)
		}
	}
	b.singleFields.Set(key, v)
}

func (b *builder) set(key string, v ast.Expr) {
	if b.current == nil {
		b.current = &OrderedMap{}
		b.allOf = append(b.allOf, (*ast.StructLit)(b.current))
	} else if b.current.exists(key) {
		b.current = &OrderedMap{}
		b.allOf = append(b.allOf, (*ast.StructLit)(b.current))
	}
	b.current.Set(key, v)
}

func (b *builder) kv(key string, value ast.Expr) *ast.StructLit {
	return ast.NewStruct(key, value)
}

func (b *builder) setNot(key string, value ast.Expr) {
	b.add(ast.NewStruct("not", b.kv(key, value)))
}

func (b *builder) finish() *ast.StructLit {
	var t *OrderedMap

	if b.filled != nil {
		return b.filled
	}
	switch len(b.allOf) {
	case 0:
		t = &OrderedMap{}

	case 1:
		t = (*OrderedMap)(b.allOf[0])

	default:
		exprs := []ast.Expr{}
		for _, s := range b.allOf {
			exprs = append(exprs, s)
		}
		t = &OrderedMap{}
		t.Set("allOf", ast.NewList(exprs...))
	}
	if b.singleFields != nil {
		b.singleFields.Elts = append(b.singleFields.Elts, t.Elts...)
		t = b.singleFields
	}
	if b.deprecated {
		t.Set("deprecated", ast.NewBool(true))
	}
	setType(t, b)
	sortSchema((*ast.StructLit)(t))
	return (*ast.StructLit)(t)
}

func (b *builder) add(t *ast.StructLit) {
	b.allOf = append(b.allOf, t)
}

func (b *builder) addConjunct(f func(*builder)) {
	c := newOASBuilder(b)
	f(c)
	b.add((*ast.StructLit)(c.finish()))
}

func (b *builder) addRef(v cue.Value, inst *cue.Instance, ref []string) {
	name := b.ctx.makeRef(inst, ref)
	b.addConjunct(func(b *builder) {
		b.set("$ref", ast.NewString(path.Join("#", b.ctx.refPrefix, name)))
	})

	if b.ctx.inst != inst {
		b.ctx.externalRefs[name] = &externalType{
			ref:   name,
			inst:  inst,
			path:  ref,
			value: v,
		}
	}
}

func (b *buildContext) makeRef(inst *cue.Instance, ref []string) string {
	a := make([]string, 0, len(ref)+3)
	if b.nameFunc != nil {
		a = append(a, b.nameFunc(inst, ref))
	} else {
		a = append(a, ref...)
	}
	return path.Join(a...)
}

func (b *builder) int64(v cue.Value) int64 {
	v, _ = v.Default()
	i, err := v.Int64()
	if err != nil {
		b.failf(v, "could not retrieve int: %v", err)
	}
	return i
}

func (b *builder) intExpr(i int64) ast.Expr {
	return &ast.BasicLit{
		Kind:  token.INT,
		Value: fmt.Sprint(i),
	}
}

func (b *builder) int(v cue.Value) ast.Expr {
	return b.intExpr(b.int64(v))
}

func (b *builder) inta(v cue.Value, offset int64) ast.Expr {
	return b.intExpr(b.int64(v) + offset)
}

func (b *builder) decode(v cue.Value) ast.Expr {
	v, _ = v.Default()
	return v.Syntax().(ast.Expr)
}

func (b *builder) big(v cue.Value) ast.Expr {
	v, _ = v.Default()
	return v.Syntax().(ast.Expr)
}
