// 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.Label == arcs[i].Label; 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.Value = 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
}
