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

import (
	"fmt"
	"math/big"
	"path"
	"regexp"

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

// TODO: skip invalid regexps containing ?! and foes.
// alternatively, fall back to  https://github.com/dlclark/regexp2

type constraint struct {
	key string

	// phase indicates on which pass c constraint should be added. This ensures
	// that constraints are applied in the correct order. For instance, the
	// "required" constraint validates that a listed field is contained in
	// "properties". For this to work, "properties" must be processed before
	// "required" and thus must have a lower phase number than the latter.
	phase int

	// Indicates the draft number in which this constraint is defined.
	draft int
	fn    constraintFunc
}

// A constraintFunc converts a given JSON Schema constraint (specified in n)
// to a CUE constraint recorded in state.
type constraintFunc func(n cue.Value, s *state)

func p0(name string, f constraintFunc) *constraint {
	return &constraint{key: name, fn: f}
}

func p1d(name string, draft int, f constraintFunc) *constraint {
	return &constraint{key: name, phase: 1, draft: draft, fn: f}
}

func p1(name string, f constraintFunc) *constraint {
	return &constraint{key: name, phase: 1, fn: f}
}

func p2(name string, f constraintFunc) *constraint {
	return &constraint{key: name, phase: 2, fn: f}
}

func p3(name string, f constraintFunc) *constraint {
	return &constraint{key: name, phase: 3, fn: f}
}

// TODO:
// writeOnly, readOnly

var constraintMap = map[string]*constraint{}

func init() {
	for _, c := range constraints {
		constraintMap[c.key] = c
	}
}

func addDefinitions(n cue.Value, s *state) {
	if n.Kind() != cue.StructKind {
		s.errf(n, `"definitions" expected an object, found %s`, n.Kind())
	}

	old := s.isSchema
	s.isSchema = true
	defer func() { s.isSchema = old }()

	s.processMap(n, func(key string, n cue.Value) {
		name := key

		var f *ast.Field

		ident := "#" + name
		if ast.IsValidIdent(ident) {
			f = &ast.Field{Value: s.schema(n, label{ident, true})}
			f.Label = ast.NewIdent(ident)
		} else {
			f = &ast.Field{Value: s.schema(n, label{"#", true}, label{name: name})}
			f.Label = ast.NewString(name)
			ident = "#"
			f = &ast.Field{
				Label: ast.NewIdent("#"),
				Value: ast.NewStruct(f),
			}
		}

		ast.SetRelPos(f, token.NewSection)
		s.definitions = append(s.definitions, f)
		s.setField(label{name: ident, isDef: true}, f)
	})
}

var constraints = []*constraint{
	// Meta data.

	p0("$schema", func(n cue.Value, s *state) {
		// Identifies this as a JSON schema and specifies its version.
		// TODO: extract version.
		s.jsonschema, _ = s.strValue(n)
	}),

	p0("$id", func(n cue.Value, s *state) {
		// URL: https://domain.com/schemas/foo.json
		// anchors: #identifier
		//
		// TODO: mark identifiers.

		// Resolution must be relative to parent $id
		// https://tools.ietf.org/html/draft-handrews-json-schema-02#section-8.2.2
		u := s.resolveURI(n)
		if u == nil {
			return
		}

		if u.Fragment != "" {
			if s.cfg.Strict {
				s.errf(n, "$id URI may not contain a fragment")
			}
			return
		}
		s.id = u

		obj := s.object(n)

		// TODO: handle the case where this is always defined and we don't want
		// to include the default value.
		obj.Elts = append(obj.Elts, &ast.Attribute{
			Text: fmt.Sprintf("@jsonschema(id=%q)", u)})
	}),

	// Generic constraint

	p1("type", func(n cue.Value, s *state) {
		var types cue.Kind
		set := func(n cue.Value) {
			str, ok := s.strValue(n)
			if !ok {
				s.errf(n, "type value should be a string")
			}
			switch str {
			case "null":
				types |= cue.NullKind
				s.setTypeUsed(n, nullType)
				// TODO: handle OpenAPI restrictions.
			case "boolean":
				types |= cue.BoolKind
				s.setTypeUsed(n, boolType)
			case "string":
				types |= cue.StringKind
				s.setTypeUsed(n, stringType)
			case "number":
				types |= cue.NumberKind
				s.setTypeUsed(n, numType)
			case "integer":
				types |= cue.IntKind
				s.setTypeUsed(n, numType)
				s.add(n, numType, ast.NewIdent("int"))
			case "array":
				types |= cue.ListKind
				s.setTypeUsed(n, arrayType)
			case "object":
				types |= cue.StructKind
				s.setTypeUsed(n, objectType)

			default:
				s.errf(n, "unknown type %q", n)
			}
		}

		switch n.Kind() {
		case cue.StringKind:
			set(n)
		case cue.ListKind:
			for i, _ := n.List(); i.Next(); {
				set(i.Value())
			}
		default:
			s.errf(n, `value of "type" must be a string or list of strings`)
		}

		s.allowedTypes &= types
	}),

	p1("enum", func(n cue.Value, s *state) {
		var a []ast.Expr
		for _, x := range s.listItems("enum", n, true) {
			a = append(a, s.value(x))
		}
		s.all.add(n, ast.NewBinExpr(token.OR, a...))
	}),

	// TODO: only allow for OpenAPI.
	p1("nullable", func(n cue.Value, s *state) {
		null := ast.NewNull()
		setPos(null, n)
		s.nullable = null
	}),

	p1d("const", 6, func(n cue.Value, s *state) {
		s.all.add(n, s.value(n))
	}),

	p1("default", func(n cue.Value, s *state) {
		sc := *s
		s.default_ = sc.value(n)
		// TODO: must validate that the default is subsumed by the normal value,
		// as CUE will otherwise broaden the accepted values with the default.
		s.examples = append(s.examples, s.default_)
	}),

	p1("deprecated", func(n cue.Value, s *state) {
		if s.boolValue(n) {
			s.deprecated = true
		}
	}),

	p1("examples", func(n cue.Value, s *state) {
		if n.Kind() != cue.ListKind {
			s.errf(n, `value of "examples" must be an array, found %v`, n.Kind)
		}
		// TODO: implement examples properly.
		// for _, n := range s.listItems("examples", n, true) {
		// 	if ex := s.value(n); !isAny(ex) {
		// 		s.examples = append(s.examples, ex)
		// 	}
		// }
	}),

	p1("description", func(n cue.Value, s *state) {
		s.description, _ = s.strValue(n)
	}),

	p1("title", func(n cue.Value, s *state) {
		s.title, _ = s.strValue(n)
	}),

	p1d("$comment", 7, func(n cue.Value, s *state) {
	}),

	p1("$defs", addDefinitions),
	p1("definitions", addDefinitions),
	p1("$ref", func(n cue.Value, s *state) {
		s.usedTypes = allTypes

		u := s.resolveURI(n)

		if u.Fragment != "" && !path.IsAbs(u.Fragment) {
			s.addErr(errors.Newf(n.Pos(), "anchors (%s) not supported", u.Fragment))
			// TODO: support anchors
			return
		}

		expr := s.makeCUERef(n, u)

		if expr == nil {
			expr = &ast.BadExpr{From: n.Pos()}
		}

		s.all.add(n, expr)
	}),

	// Combinators

	// TODO: work this out in more detail: oneOf and anyOf below have the same
	// implementation in CUE. The distinction is that for anyOf a result is
	// allowed to be ambiguous at the end, whereas for oneOf a disjunction must
	// be fully resolved. There is currently no easy way to set this distinction
	// in CUE.
	//
	// One could correctly write oneOf like this once 'not' is implemented:
	//
	//   oneOf(a, b, c) :-
	//      anyOf(
	//         allOf(a, not(b), not(c)),
	//         allOf(not(a), b, not(c)),
	//         allOf(not(a), not(b), c),
	//   ))
	//
	// This is not necessary if the values are mutually exclusive/ have a
	// discriminator.

	p2("allOf", func(n cue.Value, s *state) {
		var a []ast.Expr
		for _, v := range s.listItems("allOf", n, false) {
			x, sub := s.schemaState(v, s.allowedTypes, nil, true)
			s.allowedTypes &= sub.allowedTypes
			s.usedTypes |= sub.usedTypes
			if sub.hasConstraints() {
				a = append(a, x)
			}
		}
		if len(a) > 0 {
			s.all.add(n, ast.NewBinExpr(token.AND, a...))
		}
	}),

	p2("anyOf", func(n cue.Value, s *state) {
		var types cue.Kind
		var a []ast.Expr
		for _, v := range s.listItems("anyOf", n, false) {
			x, sub := s.schemaState(v, s.allowedTypes, nil, true)
			types |= sub.allowedTypes
			a = append(a, x)
		}
		s.allowedTypes &= types
		if len(a) > 0 {
			s.all.add(n, ast.NewBinExpr(token.OR, a...))
		}
	}),

	p2("oneOf", func(n cue.Value, s *state) {
		var types cue.Kind
		var a []ast.Expr
		hasSome := false
		for _, v := range s.listItems("oneOf", n, false) {
			x, sub := s.schemaState(v, s.allowedTypes, nil, true)
			types |= sub.allowedTypes

			// TODO: make more finegrained by making it two pass.
			if sub.hasConstraints() {
				hasSome = true
			}

			if !isAny(x) {
				a = append(a, x)
			}
		}
		s.allowedTypes &= types
		if len(a) > 0 && hasSome {
			s.usedTypes = allTypes
			s.all.add(n, ast.NewBinExpr(token.OR, a...))
		}

		// TODO: oneOf({a:x}, {b:y}, ..., not(anyOf({a:x}, {b:y}, ...))),
		// can be translated to {} | {a:x}, {b:y}, ...
	}),

	// String constraints

	p1("pattern", func(n cue.Value, s *state) {
		str, _ := n.String()
		if _, err := regexp.Compile(str); err != nil {
			if s.cfg.Strict {
				s.errf(n, "unsupported regexp: %v", err)
			}
			return
		}
		s.usedTypes |= cue.StringKind
		s.add(n, stringType, &ast.UnaryExpr{Op: token.MAT, X: s.string(n)})
	}),

	p1("minLength", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StringKind
		min := s.number(n)
		strings := s.addImport(n, "strings")
		s.add(n, stringType, ast.NewCall(ast.NewSel(strings, "MinRunes"), min))
	}),

	p1("maxLength", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StringKind
		max := s.number(n)
		strings := s.addImport(n, "strings")
		s.add(n, stringType, ast.NewCall(ast.NewSel(strings, "MaxRunes"), max))
	}),

	p1d("contentMediaType", 7, func(n cue.Value, s *state) {
		// TODO: only mark as used if it generates something.
		// s.usedTypes |= cue.StringKind
	}),

	p1d("contentEncoding", 7, func(n cue.Value, s *state) {
		// TODO: only mark as used if it generates something.
		// s.usedTypes |= cue.StringKind
		// 7bit, 8bit, binary, quoted-printable and base64.
		// RFC 2054, part 6.1.
		// https://tools.ietf.org/html/rfc2045
		// TODO: at least handle bytes.
	}),

	// Number constraints

	p1("minimum", func(n cue.Value, s *state) {
		s.usedTypes |= cue.NumberKind
		s.add(n, numType, &ast.UnaryExpr{Op: token.GEQ, X: s.number(n)})
	}),

	p1("exclusiveMinimum", func(n cue.Value, s *state) {
		// TODO: should we support Draft 4 booleans?
		s.usedTypes |= cue.NumberKind
		s.add(n, numType, &ast.UnaryExpr{Op: token.GTR, X: s.number(n)})
	}),

	p1("maximum", func(n cue.Value, s *state) {
		s.usedTypes |= cue.NumberKind
		s.add(n, numType, &ast.UnaryExpr{Op: token.LEQ, X: s.number(n)})
	}),

	p1("exclusiveMaximum", func(n cue.Value, s *state) {
		// TODO: should we support Draft 4 booleans?
		s.usedTypes |= cue.NumberKind
		s.add(n, numType, &ast.UnaryExpr{Op: token.LSS, X: s.number(n)})
	}),

	p1("multipleOf", func(n cue.Value, s *state) {
		s.usedTypes |= cue.NumberKind
		multiple := s.number(n)
		var x big.Int
		_, _ = n.MantExp(&x)
		if x.Cmp(big.NewInt(0)) != 1 {
			s.errf(n, `"multipleOf" value must be < 0; found %s`, n)
		}
		math := s.addImport(n, "math")
		s.add(n, numType, ast.NewCall(ast.NewSel(math, "MultipleOf"), multiple))
	}),

	// Object constraints

	p1("properties", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StructKind
		obj := s.object(n)

		if n.Kind() != cue.StructKind {
			s.errf(n, `"properties" expected an object, found %v`, n.Kind())
		}

		s.processMap(n, func(key string, n cue.Value) {
			// property?: value
			name := ast.NewString(key)
			expr, state := s.schemaState(n, allTypes, []label{{name: key}}, false)
			f := &ast.Field{Label: name, Value: expr}
			state.doc(f)
			f.Optional = token.Blank.Pos()
			if len(obj.Elts) > 0 && len(f.Comments()) > 0 {
				// TODO: change formatter such that either a a NewSection on the
				// field or doc comment will cause a new section.
				ast.SetRelPos(f.Comments()[0], token.NewSection)
			}
			if state.deprecated {
				switch expr.(type) {
				case *ast.StructLit:
					obj.Elts = append(obj.Elts, addTag(name, "deprecated", ""))
				default:
					f.Attrs = append(f.Attrs, internal.NewAttr("deprecated", ""))
				}
			}
			obj.Elts = append(obj.Elts, f)
			s.setField(label{name: key}, f)
		})
	}),

	p2("required", func(n cue.Value, s *state) {
		if n.Kind() != cue.ListKind {
			s.errf(n, `value of "required" must be list of strings, found %v`, n.Kind)
			return
		}

		s.usedTypes |= cue.StructKind

		// TODO: detect that properties is defined somewhere.
		// s.errf(n, `"required" without a "properties" field`)
		obj := s.object(n)

		// Create field map
		fields := map[string]*ast.Field{}
		for _, d := range obj.Elts {
			f, ok := d.(*ast.Field)
			if !ok {
				continue // Could be embedding? See cirrus.json
			}
			str, _, err := ast.LabelName(f.Label)
			if err == nil {
				fields[str] = f
			}
		}

		for _, n := range s.listItems("required", n, true) {
			str, ok := s.strValue(n)
			f := fields[str]
			if f == nil && ok {
				f := &ast.Field{
					Label: ast.NewString(str),
					Value: ast.NewIdent("_"),
				}
				fields[str] = f
				obj.Elts = append(obj.Elts, f)
				continue
			}
			if f.Optional == token.NoPos {
				s.errf(n, "duplicate required field %q", str)
			}
			f.Optional = token.NoPos
		}
	}),

	p1d("propertyNames", 6, func(n cue.Value, s *state) {
		// [=~pattern]: _
		if names, _ := s.schemaState(n, cue.StringKind, nil, false); !isAny(names) {
			s.usedTypes |= cue.StructKind
			x := ast.NewStruct(ast.NewList(names), ast.NewIdent("_"))
			s.add(n, objectType, x)
		}
	}),

	// TODO: reenable when we have proper non-monotonic contraint validation.
	// p1("minProperties", func(n cue.Value, s *state) {
	// 	s.usedTypes |= cue.StructKind

	// 	pkg := s.addImport(n, "struct")
	// 	s.addConjunct(n, ast.NewCall(ast.NewSel(pkg, "MinFields"), s.uint(n)))
	// }),

	p1("maxProperties", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StructKind

		pkg := s.addImport(n, "struct")
		x := ast.NewCall(ast.NewSel(pkg, "MaxFields"), s.uint(n))
		s.add(n, objectType, x)
	}),

	p1("dependencies", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StructKind

		// Schema and property dependencies.
		// TODO: the easiest implementation is with comprehensions.
		// The nicer implementation is with disjunctions. This has to be done
		// at the very end, replacing properties.
		/*
			*{ property?: _|_ } | {
				property: _
				schema
			}
		*/
	}),

	p2("patternProperties", func(n cue.Value, s *state) {
		s.usedTypes |= cue.StructKind
		if n.Kind() != cue.StructKind {
			s.errf(n, `value of "patternProperties" must be an an object, found %v`, n.Kind)
		}
		obj := s.object(n)
		existing := excludeFields(s.obj.Elts)
		s.processMap(n, func(key string, n cue.Value) {
			// [!~(properties) & pattern]: schema
			s.patterns = append(s.patterns,
				&ast.UnaryExpr{Op: token.NMAT, X: ast.NewString(key)})
			f := internal.EmbedStruct(ast.NewStruct(&ast.Field{
				Label: ast.NewList(ast.NewBinExpr(token.AND,
					&ast.UnaryExpr{Op: token.MAT, X: ast.NewString(key)},
					existing)),
				Value: s.schema(n),
			}))
			ast.SetRelPos(f, token.NewSection)
			obj.Elts = append(obj.Elts, f)
		})
	}),

	p3("additionalProperties", func(n cue.Value, s *state) {
		switch n.Kind() {
		case cue.BoolKind:
			s.closeStruct = !s.boolValue(n)
			if !s.closeStruct {
				s.usedTypes |= cue.StructKind
			}

		case cue.StructKind:
			s.usedTypes |= cue.StructKind
			s.closeStruct = true
			obj := s.object(n)
			if len(obj.Elts) == 0 {
				obj.Elts = append(obj.Elts, &ast.Field{
					Label: ast.NewList(ast.NewIdent("string")),
					Value: s.schema(n),
				})
				return
			}
			// [!~(properties|patternProperties)]: schema
			existing := append(s.patterns, excludeFields(obj.Elts))
			f := internal.EmbedStruct(ast.NewStruct(&ast.Field{
				Label: ast.NewList(ast.NewBinExpr(token.AND, existing...)),
				Value: s.schema(n),
			}))
			obj.Elts = append(obj.Elts, f)

		default:
			s.errf(n, `value of "additionalProperties" must be an object or boolean`)
		}
	}),

	// Array constraints.

	p1("items", func(n cue.Value, s *state) {
		s.usedTypes |= cue.ListKind
		switch n.Kind() {
		case cue.StructKind:
			elem := s.schema(n)
			ast.SetRelPos(elem, token.NoRelPos)
			s.add(n, arrayType, ast.NewList(&ast.Ellipsis{Type: elem}))

		case cue.ListKind:
			var a []ast.Expr
			for _, n := range s.listItems("items", n, true) {
				v := s.schema(n) // TODO: label with number literal.
				ast.SetRelPos(v, token.NoRelPos)
				a = append(a, v)
			}
			s.list = ast.NewList(a...)
			s.add(n, arrayType, s.list)

		default:
			s.errf(n, `value of "items" must be an object or array`)
		}
	}),

	p1("additionalItems", func(n cue.Value, s *state) {
		switch n.Kind() {
		case cue.BoolKind:
			// TODO: support

		case cue.StructKind:
			if s.list != nil {
				s.usedTypes |= cue.ListKind
				elem := s.schema(n)
				s.list.Elts = append(s.list.Elts, &ast.Ellipsis{Type: elem})
			}

		default:
			s.errf(n, `value of "additionalItems" must be an object or boolean`)
		}
	}),

	p1("contains", func(n cue.Value, s *state) {
		s.usedTypes |= cue.ListKind
		list := s.addImport(n, "list")
		// TODO: Passing non-concrete values is not yet supported in CUE.
		if x := s.schema(n); !isAny(x) {
			x := ast.NewCall(ast.NewSel(list, "Contains"), clearPos(x))
			s.add(n, arrayType, x)
		}
	}),

	// TODO: min/maxContains

	p1("minItems", func(n cue.Value, s *state) {
		s.usedTypes |= cue.ListKind
		a := []ast.Expr{}
		p, err := n.Uint64()
		if err != nil {
			s.errf(n, "invalid uint")
		}
		for ; p > 0; p-- {
			a = append(a, ast.NewIdent("_"))
		}
		s.add(n, arrayType, ast.NewList(append(a, &ast.Ellipsis{})...))

		// TODO: use this once constraint resolution is properly implemented.
		// list := s.addImport(n, "list")
		// s.addConjunct(n, ast.NewCall(ast.NewSel(list, "MinItems"), clearPos(s.uint(n))))
	}),

	p1("maxItems", func(n cue.Value, s *state) {
		s.usedTypes |= cue.ListKind
		list := s.addImport(n, "list")
		x := ast.NewCall(ast.NewSel(list, "MaxItems"), clearPos(s.uint(n)))
		s.add(n, arrayType, x)

	}),

	p1("uniqueItems", func(n cue.Value, s *state) {
		s.usedTypes |= cue.ListKind
		if s.boolValue(n) {
			list := s.addImport(n, "list")
			s.add(n, arrayType, ast.NewCall(ast.NewSel(list, "UniqueItems")))
		}
	}),
}

func clearPos(e ast.Expr) ast.Expr {
	ast.SetRelPos(e, token.NoRelPos)
	return e
}
