// 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 trim removes fields that may be inferred from another mixed in value
// that "dominates" it. For instance, a value that is merged in from a
// definition is considered to dominate a value from a regular struct that
// mixes in this definition. Values derived from constraints and comprehensions
// can also dominate other fields.
//
// A value A is considered to be implied by a value B if A subsumes the default
// value of B. For instance, if a definition defines a field `a: *1 | int` and
// mixed in with a struct that defines a field `a: 1 | 2`, then the latter can
// be removed because a definition field dominates a regular field and because
// the latter subsumes the default value of the former.
//
//
// Examples:
//
// 	light: [string]: {
// 		room:          string
// 		brightnessOff: *0.0 | >=0 & <=100.0
// 		brightnessOn:  *100.0 | >=0 & <=100.0
// 	}
//
// 	light: ceiling50: {
// 		room:          "MasterBedroom"
// 		brightnessOff: 0.0    // this line
// 		brightnessOn:  100.0  // and this line will be removed
// 	}
//
// Results in:
//
// 	// Unmodified: light: [string]: { ... }
//
// 	light: ceiling50: {
// 		room: "MasterBedroom"
// 	}
//
package trim

import (
	"io"
	"os"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/ast/astutil"
	"cuelang.org/go/internal"
	"cuelang.org/go/internal/core/adt"
	"cuelang.org/go/internal/core/debug"
	"cuelang.org/go/internal/core/runtime"
	"cuelang.org/go/internal/core/subsume"
)

// Config configures trim options.
type Config struct {
	Trace bool
}

// Files trims fields in the given files that can be implied from other fields,
// as can be derived from the evaluated values in inst.
// Trimming is done on a best-effort basis and only when the removed field
// is clearly implied by another field, rather than equal sibling fields.
func Files(files []*ast.File, inst *cue.Instance, cfg *Config) error {
	rx, vx := internal.CoreValue(inst.Value())
	r := rx.(*runtime.Runtime)
	v := vx.(*adt.Vertex)

	t := &trimmer{
		Config:  *cfg,
		ctx:     adt.NewContext(r, v),
		remove:  map[ast.Node]bool{},
		exclude: map[ast.Node]bool{},
		debug:   Debug,
		w:       os.Stderr,
	}

	t.findSubordinates(v)

	// Remove subordinate values from files.
	for _, f := range files {
		astutil.Apply(f, func(c astutil.Cursor) bool {
			if f, ok := c.Node().(*ast.Field); ok && t.remove[f.Value] && !t.exclude[f.Value] {
				c.Delete()
			}
			return true
		}, nil)
		if err := astutil.Sanitize(f); err != nil {
			return err
		}
	}

	return nil
}

type trimmer struct {
	Config

	ctx     *adt.OpContext
	remove  map[ast.Node]bool
	exclude map[ast.Node]bool

	debug  bool
	indent int
	w      io.Writer
}

var Debug bool = false

func (t *trimmer) markRemove(c adt.Conjunct) {
	if src := c.Expr().Source(); src != nil {
		t.remove[src] = true
		if t.debug {
			t.logf("removing %s", debug.NodeString(t.ctx, c.Expr(), nil))
		}
	}
}

func (t *trimmer) markKeep(c adt.Conjunct) {
	if isDominator(c) {
		return
	}
	if src := c.Expr().Source(); src != nil {
		t.exclude[src] = true
		if t.debug {
			t.logf("keeping")
		}
	}
}

const dominatorNode = adt.ComprehensionSpan | adt.DefinitionSpan | adt.ConstraintSpan

// isDominator reports whether a node can remove other nodes.
func isDominator(c adt.Conjunct) bool {
	return c.CloseInfo.IsInOneOf(dominatorNode)
}

// Removable reports whether a non-dominator conjunct can be removed. This is
// not the case if it has pattern constraints that could turn into dominator
// nodes.
func removable(c adt.Conjunct, v *adt.Vertex) bool {
	return c.CloseInfo.FieldTypes&(adt.HasAdditional|adt.HasPattern) == 0
}

// Roots of constraints are not allowed to strip conjuncts by
// themselves as it will eliminate the reason for the trigger.
func (t *trimmer) allowRemove(v *adt.Vertex) bool {
	for _, c := range v.Conjuncts {
		isDom := isDominator(c)
		loc := c.CloseInfo.Location() != c.Expr()
		isSpan := c.CloseInfo.RootSpanType() != adt.ConstraintSpan
		if isDom && (loc || isSpan) {
			return true
		}
	}
	return false
}

// A parent may be removed if there is not a `no` and there is at least one
// `yes`. A `yes` is proves that there is at least one node that is not a
// dominator node and that we are not removing nodes from a declaration of a
// dominator itself.
const (
	no = 1 << iota
	maybe
	yes
)

func (t *trimmer) findSubordinates(v *adt.Vertex) (result int) {
	defer un(t.trace(v))
	defer func() {
		if result == no {
			for _, c := range v.Conjuncts {
				t.markKeep(c)
			}
		}
	}()

	// TODO(structure sharing): do not descend into vertices whose parent is not
	// equal to the parent. This is not relevant at this time, but may be so in
	// the future.

	if len(v.Arcs) > 0 {
		var match int
		for _, a := range v.Arcs {
			match |= t.findSubordinates(a)
		}

		// This also skips embedded scalars if not all fields are removed. In
		// this case we need to preserve the scalar to keep the type of the
		// struct intact, which might as well be done by not removing the scalar
		// type.
		if match&yes == 0 || match&no != 0 {
			return match
		}
	}

	if !t.allowRemove(v) {
		return no
	}

	switch v.BaseValue.(type) {
	case *adt.StructMarker, *adt.ListMarker:
		// Rely on previous processing of the Arcs and the fact that we take the
		// default value to check dominator subsumption, meaning that we don't
		// have to check additional optional constraints to pass subsumption.

	default:
		doms := &adt.Vertex{}
		hasSubs := false

		for _, c := range v.Conjuncts {
			if isDominator(c) {
				doms.AddConjunct(c)
			} else {
				hasSubs = true
			}
		}

		if !hasSubs {
			return maybe // only if there are siblings to be removed.
		}

		doms.Finalize(t.ctx)
		doms = doms.Default()

		// This is not necessary, but seems like it may result in more
		// user-friendly semantics.
		if doms.IsErr() || v.IsErr() {
			return no
		}

		// TODO: since we take v, instead of the unification of subordinate
		// values, it should suffice to take equality here:
		//    doms ⊑ subs  ==> doms == subs&doms
		if err := subsume.Value(t.ctx, v, doms); err != nil {
			return no
		}
	}

	for _, c := range v.Conjuncts {
		if !isDominator(c) && removable(c, v) {
			t.markRemove(c)
		}
	}

	return yes
}
