// Copyright 2018 The 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 cue

// TODO: nodeRefs are currently not updated if the structs they point to are
// updated. Handing this in uses of rewrite is tedious and hard to get correct.
// Make this a general mechanism. This can be done using a Tomabechi-like
// approach of associating copies with nodes in one pass, and then make a
// complete copy in a second.

type rewriteFunc func(ctx *context, v value) (value, bool)

func rewrite(ctx *context, v value, fn rewriteFunc) value {
	v, descend := fn(ctx, v)
	if !descend {
		return v
	}
	return v.rewrite(ctx, fn)
}

func (x *nodeRef) rewrite(ctx *context, fn rewriteFunc) value {
	return x
}

func (x *closeIfStruct) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.value, fn)
	if v == x.value {
		return x
	}
	return wrapFinalize(ctx, v)
}

func (x *structLit) rewrite(ctx *context, fn rewriteFunc) value {
	emit := x.emit
	if emit != nil {
		emit = rewrite(ctx, x.emit, fn)
	}
	arcs := make(arcs, len(x.arcs))
	obj := &structLit{baseValue: x.baseValue, emit: emit, arcs: arcs}
	changed := emit == x.emit
	for i, a := range x.arcs {
		a.setValue(rewrite(ctx, a.v, fn))
		changed = changed || arcs[i].v != a.v
		arcs[i] = a
	}
	if !changed {
		return x
	}
	return obj
}

func (x *selectorExpr) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.x, fn)
	if v == x.x {
		return x
	}
	return &selectorExpr{x.baseValue, v, x.feature}
}

func (x *indexExpr) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.x, fn)
	index := rewrite(ctx, x.index, fn)
	if v == x.x && index == x.index {
		return x
	}
	return &indexExpr{x.baseValue, v, index}
}

// Even more boring stuff below.

func (x *builtin) rewrite(ctx *context, fn rewriteFunc) value     { return x }
func (x *top) rewrite(ctx *context, fn rewriteFunc) value         { return x }
func (x *bottom) rewrite(ctx *context, fn rewriteFunc) value      { return x }
func (x *basicType) rewrite(ctx *context, fn rewriteFunc) value   { return x }
func (x *nullLit) rewrite(ctx *context, fn rewriteFunc) value     { return x }
func (x *boolLit) rewrite(ctx *context, fn rewriteFunc) value     { return x }
func (x *stringLit) rewrite(ctx *context, fn rewriteFunc) value   { return x }
func (x *bytesLit) rewrite(ctx *context, fn rewriteFunc) value    { return x }
func (x *numLit) rewrite(ctx *context, fn rewriteFunc) value      { return x }
func (x *durationLit) rewrite(ctx *context, fn rewriteFunc) value { return x }

func (x *customValidator) rewrite(ctx *context, fn rewriteFunc) value {
	args := make([]evaluated, len(x.args))
	changed := false
	for i, a := range x.args {
		v := rewrite(ctx, a, fn)
		args[i] = v.(evaluated)
		changed = changed || v != a
	}
	if !changed {
		return x
	}
	return &customValidator{baseValue: x.baseValue, args: args, call: x.call}
}

func (x *bound) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.value, fn)
	if v == x.value {
		return x
	}
	return newBound(ctx, x.baseValue, x.op, x.k, v)
}

func (x *interpolation) rewrite(ctx *context, fn rewriteFunc) value {
	parts := make([]value, len(x.parts))
	changed := false
	for i, p := range x.parts {
		parts[i] = rewrite(ctx, p, fn)
		changed = changed || parts[i] != p
	}
	if !changed {
		return x
	}
	return &interpolation{x.baseValue, x.k, parts}
}

func (x *list) rewrite(ctx *context, fn rewriteFunc) value {
	elem := rewrite(ctx, x.elem, fn).(*structLit)
	typ := rewrite(ctx, x.typ, fn)
	len := rewrite(ctx, x.len, fn)
	if elem == x.elem && typ == x.typ && len == x.len {
		return x
	}
	return &list{x.baseValue, elem, typ, len}
}

func (x *sliceExpr) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.x, fn)
	var lo, hi value
	if x.lo != nil {
		lo = rewrite(ctx, x.lo, fn)
	}
	if x.hi != nil {
		hi = rewrite(ctx, x.hi, fn)
	}
	if v == x.x && lo == x.lo && hi == x.hi {
		return x
	}
	return &sliceExpr{x.baseValue, v, lo, hi}
}

func (x *callExpr) rewrite(ctx *context, fn rewriteFunc) value {
	args := make([]value, len(x.args))
	changed := false
	for i, a := range x.args {
		v := rewrite(ctx, a, fn)
		args[i] = v
		changed = changed || v != a
	}
	v := rewrite(ctx, x.x, fn)
	if !changed && v == x.x {
		return x
	}
	return &callExpr{baseValue: x.baseValue, x: v, args: args}
}

func (x *lambdaExpr) rewrite(ctx *context, fn rewriteFunc) value {
	arcs := make([]arc, len(x.arcs))
	changed := false
	for i, a := range x.arcs {
		v := rewrite(ctx, a.v, fn)
		arcs[i] = arc{feature: a.feature, v: v}
		changed = changed || v != a.v
	}
	value := rewrite(ctx, x.value, fn)
	if !changed && value == x.value {
		return x
	}
	return &lambdaExpr{x.baseValue, &params{arcs}, value}
}

func (x *unaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
	v := rewrite(ctx, x.x, fn)
	if v == x.x {
		return x
	}
	return &unaryExpr{x.baseValue, x.op, v}
}

func (x *binaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
	left := rewrite(ctx, x.left, fn)
	right := rewrite(ctx, x.right, fn)
	if left == x.left && right == x.right {
		return x
	}
	return updateBin(ctx, &binaryExpr{x.baseValue, x.op, left, right})
}

func (x *unification) rewrite(ctx *context, fn rewriteFunc) value {
	values := make([]evaluated, len(x.values))
	changed := false
	for i, v := range x.values {
		values[i] = rewrite(ctx, v, fn).(evaluated)
		changed = changed || v != values[i]
	}
	if !changed {
		return x
	}
	return &unification{x.baseValue, values}
}

func (x *disjunction) rewrite(ctx *context, fn rewriteFunc) value {
	values := make([]dValue, len(x.values))
	changed := false
	for i, d := range x.values {
		v := rewrite(ctx, d.val, fn)
		values[i] = dValue{v, d.marked}
		changed = changed || v != d.val
	}
	if !changed {
		return x
	}
	return &disjunction{x.baseValue, values, x.errors, x.hasDefaults}
}

func (x *listComprehension) rewrite(ctx *context, fn rewriteFunc) value {
	clauses := rewrite(ctx, x.clauses, fn).(yielder)
	if clauses == x.clauses {
		return x
	}
	return &listComprehension{x.baseValue, clauses}
}

func (x *structComprehension) rewrite(ctx *context, fn rewriteFunc) value {
	clauses := rewrite(ctx, x.clauses, fn).(yielder)
	if clauses == x.clauses {
		return x
	}
	return &structComprehension{x.baseValue, clauses}
}

func (x *fieldComprehension) rewrite(ctx *context, fn rewriteFunc) value {
	key := rewrite(ctx, x.key, fn)
	val := rewrite(ctx, x.val, fn)
	if key == x.key && val == x.val {
		return x
	}
	return &fieldComprehension{x.baseValue, key, val, x.opt, x.def, x.doc, x.attrs}
}

func (x *yield) rewrite(ctx *context, fn rewriteFunc) value {
	value := rewrite(ctx, x.value, fn)
	if value == x.value {
		return x
	}
	return &yield{x.baseValue, value}
}

func (x *guard) rewrite(ctx *context, fn rewriteFunc) value {
	condition := rewrite(ctx, x.condition, fn)
	value := rewrite(ctx, x.value, fn).(yielder)
	if condition == x.condition && value == x.value {
		return x
	}
	return &guard{x.baseValue, condition, value}
}

func (x *feed) rewrite(ctx *context, fn rewriteFunc) value {
	source := rewrite(ctx, x.source, fn)
	lambda := rewrite(ctx, x.fn, fn).(*lambdaExpr)
	if source == x.source && lambda == x.fn {
		return x
	}
	return &feed{x.baseValue, source, lambda}
}
