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

// This file contains functionality for structural schema, a subset of OpenAPI
// used for CRDs.
//
// See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/ for details.
//
// Insofar definitions are compatible, openapi normalizes to structural whenever
// possible.
//
// A core structural schema is only made out of the following fields:
//
// - properties
// - items
// - additionalProperties
// - type
// - nullable
// - title
// - descriptions.
//
// Where the types must be defined for all fields.
//
// In addition, the value validations constraints may be used as defined in
// OpenAPI, with the restriction that
//  - within the logical constraints anyOf, allOf, oneOf, and not
//    additionalProperties, type, nullable, title, and description may not be used.
//  - all mentioned fields must be defined in the core schema.
//
// It appears that CRDs do not allow references.
//

import (
	"cuelang.org/go/cue"
	"cuelang.org/go/cue/ast"
)

// newCoreBuilder returns a builder that represents a structural schema.
func newCoreBuilder(c *buildContext) *builder {
	b := newRootBuilder(c)
	b.properties = map[string]*builder{}
	return b
}

func (b *builder) coreSchemaWithName(name string) *ast.StructLit {
	oldPath := b.ctx.path
	b.ctx.path = append(b.ctx.path, name)
	s := b.coreSchema()
	b.ctx.path = oldPath
	return s
}

// coreSchema creates the core part of a structural OpenAPI.
func (b *builder) coreSchema() *ast.StructLit {
	switch b.kind {
	case cue.ListKind:
		if b.items != nil {
			b.setType("array", "")
			schema := b.items.coreSchemaWithName("*")
			b.setSingle("items", schema, false)
		}

	case cue.StructKind:
		p := &OrderedMap{}
		for _, k := range b.keys {
			sub := b.properties[k]
			p.Set(k, sub.coreSchemaWithName(k))
		}
		if p.len() > 0 || b.items != nil {
			b.setType("object", "")
		}
		if p.len() > 0 {
			b.setSingle("properties", (*ast.StructLit)(p), false)
		}
		// TODO: in Structural schema only one of these is allowed.
		if b.items != nil {
			schema := b.items.coreSchemaWithName("*")
			b.setSingle("additionalProperties", schema, false)
		}
	}

	// If there was only a single value associated with this node, we can
	// safely assume there were no disjunctions etc. In structural mode this
	// is the only chance we get to set certain properties.
	if len(b.values) == 1 {
		return b.fillSchema(b.values[0])
	}

	// TODO: do type analysis if we have multiple values and piece out more
	// information that applies to all possible instances.

	return b.finish()
}

// buildCore collects the CUE values for the structural OpenAPI tree.
// To this extent, all fields of both conjunctions and disjunctions are
// collected in a single properties map.
func (b *builder) buildCore(v cue.Value) {
	if !b.ctx.expandRefs {
		_, r := v.Reference()
		if len(r) > 0 {
			return
		}
	}
	b.getDoc(v)
	format := extractFormat(v)
	if format != "" {
		b.format = format
	} else {
		v = v.Eval()
		b.kind = v.IncompleteKind()

		switch b.kind {
		case cue.StructKind:
			if typ, ok := v.Elem(); ok {
				if b.items == nil {
					b.items = newCoreBuilder(b.ctx)
				}
				b.items.buildCore(typ)
			}
			b.buildCoreStruct(v)

		case cue.ListKind:
			if typ, ok := v.Elem(); ok {
				if b.items == nil {
					b.items = newCoreBuilder(b.ctx)
				}
				b.items.buildCore(typ)
			}
		}
	}

	for _, bv := range b.values {
		if bv.Equals(v) {
			return
		}
	}
	b.values = append(b.values, v)
}

func (b *builder) buildCoreStruct(v cue.Value) {
	op, args := v.Expr()
	switch op {
	case cue.OrOp, cue.AndOp:
		for _, v := range args {
			b.buildCore(v)
		}
	}
	for i, _ := v.Fields(cue.Optional(true), cue.Hidden(false)); i.Next(); {
		label := i.Label()
		sub, ok := b.properties[label]
		if !ok {
			sub = newCoreBuilder(b.ctx)
			b.properties[label] = sub
			b.keys = append(b.keys, label)
		}
		sub.buildCore(i.Value())
	}
}
