// 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 attribute // import "go.opentelemetry.io/otel/attribute"

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

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

type oneIterator struct {
	iter Iterator
	done bool
	attr KeyValue
}

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

// Label returns current KeyValue. Must be called only after Next returns
// true.
//
// Deprecated: Use Attribute instead.
func ( *Iterator) () KeyValue {
	return .Attribute()
}

// Attribute returns the current KeyValue of the Iterator. It must be called
// only after Next returns true.
func ( *Iterator) () KeyValue {
	,  := .storage.Get(.idx)
	return 
}

// IndexedLabel returns current index and attribute. Must be called only
// after Next returns true.
//
// Deprecated: Use IndexedAttribute instead.
func ( *Iterator) () (int, KeyValue) {
	return .idx, .Attribute()
}

// IndexedAttribute returns current index and attribute. Must be called only
// after Next returns true.
func ( *Iterator) () (int, KeyValue) {
	return .idx, .Attribute()
}

// Len returns a number of attributes in the iterated set.
func ( *Iterator) () int {
	return .storage.Len()
}

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

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

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

func ( *oneIterator) () {
	if .done = !.iter.Next(); !.done {
		.attr = .iter.Attribute()
	}
}

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

// Label returns the current value after Next() returns true.
//
// Deprecated: Use Attribute instead.
func ( *MergeIterator) () KeyValue {
	return .current
}

// Attribute returns the current value after Next() returns true.
func ( *MergeIterator) () KeyValue {
	return .current
}