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

import (
	"sort"
)

// A mergedValues type merges structs without unifying their templates.
// It evaluates structs in parallel and then creates a new mergedValues
// for each duplicate arc. The mergedValues do not reappear once there is
// only a single value per arc.
//
// This is used to merge different instances which may have incompatible
// specializations, but have disjuncts objects that may otherwise be shared
// in the same namespace.
type mergedValues struct {
	baseValue
	values []value
}

func (x *mergedValues) evalPartial(ctx *context) evaluated {
	var structs []*structLit
	for _, v := range x.values {
		v = v.evalPartial(ctx)
		o, ok := v.(*structLit)
		if !ok {
			v := x.values[0]
			for _, w := range x.values[1:] {
				v = mkBin(ctx, w.Pos(), opUnify, v, w)
			}
			return v.evalPartial(ctx)
		}
		o, err := o.expandFields(ctx)
		if err != nil {
			return err
		}
		structs = append(structs, o)
	}

	// Pre-expand the arcs so that we can discard the templates.
	obj := &structLit{
		baseValue: structs[0].baseValue,
	}
	var arcs arcs
	for _, v := range structs {
		for i := 0; i < len(v.arcs); i++ {
			w := v.iterAt(ctx, i)
			arcs = append(arcs, w)
		}
	}
	obj.arcs = arcs
	sort.Stable(obj)

	values := []value{}
	for _, v := range structs {
		if v.emit != nil {
			values = append(values, v.emit)
		}
	}
	switch len(values) {
	case 0:
	case 1:
		obj.emit = values[0]
	default:
		obj.emit = &mergedValues{values[0].base(), values}
	}

	// merge arcs
	k := 0
	for i := 0; i < len(arcs); k++ {
		a := arcs[i]
		// TODO: consider storing the evaluated value. This is a performance
		// versus having more information tradeoff. It results in the same
		// value.
		values := []value{a.v}
		for i++; i < len(arcs) && a.feature == arcs[i].feature; i++ {
			values = append(values, arcs[i].v)
			a.optional = a.optional && arcs[i].optional
			var err evaluated
			a.attrs, err = unifyAttrs(ctx, a.v, a.attrs, arcs[i].attrs)
			if err != nil {
				return err
			}
			a.docs = mergeDocs(a.docs, arcs[i].docs)
		}
		if len(values) == 1 {
			arcs[k] = a
			continue
		}
		a.cache = nil
		a.v = &mergedValues{a.v.base(), values}
		arcs[k] = a
	}
	obj.arcs = arcs[:k]
	return obj
}

func (x *mergedValues) kind() kind {
	k := x.values[0].kind()
	for _, v := range x.values {
		k = unifyType(k, v.kind())
	}
	return k
}

func (x *mergedValues) rewrite(ctx *context, fn rewriteFunc) value {
	vs := make([]value, len(x.values))
	for i, v := range x.values {
		vs[i] = rewrite(ctx, v, fn)
	}
	return &mergedValues{x.baseValue, vs}
}

func (x *mergedValues) subsumesImpl(s *subsumer, v value) bool {
	return false
}
