// 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) {
	b.pushNode(v)
	defer b.popNode()

	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.checkCycle(typ) {
					return
				}
				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.checkCycle(typ) {
					return
				}
				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())
	}
}
