// Copyright The OpenTelemetry 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 label

// Iterator allows iterating over the set of labels in order,
// sorted by key.
type Iterator struct {
	storage *Set
	idx     int
}

// MergeIterator supports iterating over two sets of labels while
// eliminating duplicate values from the combined set.  The first
// iterator value takes precedence.
type MergeItererator struct {
	one     oneIterator
	two     oneIterator
	current KeyValue
}

type oneIterator struct {
	iter  Iterator
	done  bool
	label KeyValue
}

// Next moves the iterator to the next position. Returns false if there
// are no more labels.
func (i *Iterator) Next() bool {
	i.idx++
	return i.idx < i.Len()
}

// Label returns current KeyValue. Must be called only after Next returns
// true.
func (i *Iterator) Label() KeyValue {
	kv, _ := i.storage.Get(i.idx)
	return kv
}

// Attribute is a synonym for Label().
func (i *Iterator) Attribute() KeyValue {
	return i.Label()
}

// IndexedLabel returns current index and label. Must be called only
// after Next returns true.
func (i *Iterator) IndexedLabel() (int, KeyValue) {
	return i.idx, i.Label()
}

// Len returns a number of labels in the iterator's `*Set`.
func (i *Iterator) Len() int {
	return i.storage.Len()
}

// ToSlice is a convenience function that creates a slice of labels
// from the passed iterator. The iterator is set up to start from the
// beginning before creating the slice.
func (i *Iterator) ToSlice() []KeyValue {
	l := i.Len()
	if l == 0 {
		return nil
	}
	i.idx = -1
	slice := make([]KeyValue, 0, l)
	for i.Next() {
		slice = append(slice, i.Label())
	}
	return slice
}

// NewMergeIterator returns a MergeIterator for merging two label sets
// Duplicates are resolved by taking the value from the first set.
func NewMergeIterator(s1, s2 *Set) MergeItererator {
	mi := MergeItererator{
		one: makeOne(s1.Iter()),
		two: makeOne(s2.Iter()),
	}
	return mi
}

func makeOne(iter Iterator) oneIterator {
	oi := oneIterator{
		iter: iter,
	}
	oi.advance()
	return oi
}

func (oi *oneIterator) advance() {
	if oi.done = !oi.iter.Next(); !oi.done {
		oi.label = oi.iter.Label()
	}
}

// Next returns true if there is another label available.
func (m *MergeItererator) Next() bool {
	if m.one.done && m.two.done {
		return false
	}
	if m.one.done {
		m.current = m.two.label
		m.two.advance()
		return true
	}
	if m.two.done {
		m.current = m.one.label
		m.one.advance()
		return true
	}
	if m.one.label.Key == m.two.label.Key {
		m.current = m.one.label // first iterator label value wins
		m.one.advance()
		m.two.advance()
		return true
	}
	if m.one.label.Key < m.two.label.Key {
		m.current = m.one.label
		m.one.advance()
		return true
	}
	m.current = m.two.label
	m.two.advance()
	return true
}

// Label returns the current value after Next() returns true.
func (m *MergeItererator) Label() KeyValue {
	return m.current
}
