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

import (
	"strconv"

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

// Profile configures a diff operation.
type Profile struct {
	Concrete bool
}

var (
	// Schema is the standard profile used for comparing schema.
	Schema = &Profile{}

	// Final is the standard profile for comparing data.
	Final = &Profile{
		Concrete: true,
	}
)

// Diff is a shorthand for Schema.Diff.
func Diff(x, y cue.Value) (Kind, *EditScript) {
	return Schema.Diff(x, y)
}

// Diff returns an edit script representing the difference between x and y.
func (p *Profile) Diff(x, y cue.Value) (Kind, *EditScript) {
	d := differ{cfg: *p}
	return d.diffValue(x, y)
}

// Kind identifies the kind of operation of an edit script.
type Kind uint8

const (
	// Identity indicates that a value pair is identical in both list X and Y.
	Identity Kind = iota
	// UniqueX indicates that a value only exists in X and not Y.
	UniqueX
	// UniqueY indicates that a value only exists in Y and not X.
	UniqueY
	// Modified indicates that a value pair is a modification of each other.
	Modified
)

// EditScript represents the series of differences between two CUE values.
// x and y must be either both list or struct.
type EditScript struct {
	x, y  cue.Value
	edits []Edit
}

// Len returns the number of edits.
func (es *EditScript) Len() int {
	return len(es.edits)
}

// Label returns a string representation of the label.
//
func (es *EditScript) LabelX(i int) string {
	e := es.edits[i]
	p := e.XPos()
	if p < 0 {
		return ""
	}
	return label(es.x, p)
}

func (es *EditScript) LabelY(i int) string {
	e := es.edits[i]
	p := e.YPos()
	if p < 0 {
		return ""
	}
	return label(es.y, p)
}

// TODO: support label expressions.
func label(v cue.Value, i int) string {
	st, err := v.Struct()
	if err != nil {
		return ""
	}

	// TODO: return formatted expression for optionals.
	f := st.Field(i)
	str := f.Name
	if !ast.IsValidIdent(str) {
		str = strconv.Quote(str)
	}
	if f.IsOptional {
		str += "?"
	}
	str += ":"
	return str
}

// ValueX returns the value of X involved at step i.
func (es *EditScript) ValueX(i int) (v cue.Value) {
	p := es.edits[i].XPos()
	if p < 0 {
		return v
	}
	st, err := es.x.Struct()
	if err != nil {
		return v
	}
	return st.Field(p).Value
}

// ValueY returns the value of Y involved at step i.
func (es *EditScript) ValueY(i int) (v cue.Value) {
	p := es.edits[i].YPos()
	if p < 0 {
		return v
	}
	st, err := es.y.Struct()
	if err != nil {
		return v
	}
	return st.Field(p).Value
}

// Edit represents a single operation within an edit-script.
type Edit struct {
	kind Kind
	xPos int32       // 0 if UniqueY
	yPos int32       // 0 if UniqueX
	sub  *EditScript // non-nil if Modified
}

func (e Edit) Kind() Kind { return e.kind }
func (e Edit) XPos() int  { return int(e.xPos - 1) }
func (e Edit) YPos() int  { return int(e.yPos - 1) }

type differ struct {
	cfg     Profile
	options []cue.Option
	errs    errors.Error
}

func (d *differ) diffValue(x, y cue.Value) (Kind, *EditScript) {
	if d.cfg.Concrete {
		x, _ = x.Default()
		y, _ = y.Default()
	}
	if x.IncompleteKind() != y.IncompleteKind() {
		return Modified, nil
	}

	switch xc, yc := x.IsConcrete(), y.IsConcrete(); {
	case xc != yc:
		return Modified, nil

	case xc && yc:
		switch k := x.Kind(); k {
		case cue.StructKind:
			return d.diffStruct(x, y)

		case cue.ListKind:
			return d.diffList(x, y)
		}
		fallthrough

	default:
		// In concrete mode we do not care about non-concrete values.
		if d.cfg.Concrete {
			return Identity, nil
		}

		if !x.Equals(y) {
			return Modified, nil
		}
	}

	return Identity, nil
}

func (d *differ) diffStruct(x, y cue.Value) (Kind, *EditScript) {
	sx, _ := x.Struct()
	sy, _ := y.Struct()

	// Best-effort topological sort, prioritizing x over y, using a variant of
	// Kahn's algorithm (see, for instance
	// https://www.geeksforgeeks.org/topological-sorting-indegree-based-solution/).
	// We assume that the order of the elements of each value indicate an edge
	// in the graph. This means that only the next unprocessed nodes can be
	// those with no incoming edges.
	xMap := make(map[string]int32, sx.Len())
	yMap := make(map[string]int32, sy.Len())
	for i := 0; i < sx.Len(); i++ {
		xMap[sx.Field(i).Name] = int32(i + 1)
	}
	for i := 0; i < sy.Len(); i++ {
		yMap[sy.Field(i).Name] = int32(i + 1)
	}

	edits := []Edit{}
	differs := false

	var xi, yi int
	var xf, yf cue.FieldInfo
	for xi < sx.Len() || yi < sy.Len() {
		// Process zero nodes
		for ; xi < sx.Len(); xi++ {
			xf = sx.Field(xi)
			yp := yMap[xf.Name]
			if yp > 0 {
				break
			}
			edits = append(edits, Edit{UniqueX, int32(xi + 1), 0, nil})
			differs = true
		}
		for ; yi < sy.Len(); yi++ {
			yf = sy.Field(yi)
			if yMap[yf.Name] == 0 {
				// already done
				continue
			}
			xp := xMap[yf.Name]
			if xp > 0 {
				break
			}
			yMap[yf.Name] = 0
			edits = append(edits, Edit{UniqueY, 0, int32(yi + 1), nil})
			differs = true
		}

		// Compare nodes
		for ; xi < sx.Len(); xi++ {
			xf = sx.Field(xi)

			yp := yMap[xf.Name]
			if yp == 0 {
				break
			}
			// If yp != xi+1, the topological sort was not possible.
			yMap[xf.Name] = 0

			yf := sy.Field(int(yp - 1))

			kind := Identity
			var script *EditScript
			switch {
			case xf.IsDefinition != yf.IsDefinition,
				xf.IsOptional != yf.IsOptional:
				kind = Modified

			default:
				xv := xf.Value
				yv := yf.Value
				// TODO(perf): consider evaluating lazily.
				kind, script = d.diffValue(xv, yv)
			}

			edits = append(edits, Edit{kind, int32(xi + 1), yp, script})
			if kind != Identity {
				differs = true
			}
		}
	}
	if !differs {
		return Identity, nil
	}
	return Modified, &EditScript{x: x, y: y, edits: edits}
}

// TODO: right now we do a simple element-by-element comparison. Instead,
// use an algorithm that approximates a minimal Levenshtein distance, like the
// one in github.com/google/go-cmp/internal/diff.
func (d *differ) diffList(x, y cue.Value) (Kind, *EditScript) {
	ix, _ := x.List()
	iy, _ := y.List()

	edits := []Edit{}
	differs := false
	i := int32(1)

	for {
		// TODO: This would be much easier with a Next/Done API.
		hasX := ix.Next()
		hasY := iy.Next()
		if !hasX {
			for hasY {
				differs = true
				edits = append(edits, Edit{UniqueY, 0, i, nil})
				hasY = iy.Next()
				i++
			}
			break
		}
		if !hasY {
			for hasX {
				differs = true
				edits = append(edits, Edit{UniqueX, i, 0, nil})
				hasX = ix.Next()
				i++
			}
			break
		}

		// Both x and y have a value.
		kind, script := d.diffValue(ix.Value(), iy.Value())
		if kind != Identity {
			differs = true
		}
		edits = append(edits, Edit{kind, i, i, script})
		i++
	}
	if !differs {
		return Identity, nil
	}
	return Modified, &EditScript{x: x, y: y, edits: edits}
}
