package bbolt

import (
	
	
	
)

// Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order.
// Cursors see nested buckets with value == nil.
// Cursors can be obtained from a transaction and are valid as long as the transaction is open.
//
// Keys and values returned from the cursor are only valid for the life of the transaction.
//
// Changing data while traversing with a cursor may cause it to be invalidated
// and return unexpected keys and/or values. You must reposition your cursor
// after mutating data.
type Cursor struct {
	bucket *Bucket
	stack  []elemRef
}

// Bucket returns the bucket that this cursor was created from.
func ( *Cursor) () *Bucket {
	return .bucket
}

// First moves the cursor to the first item in the bucket and returns its key and value.
// If the bucket is empty then a nil key and value are returned.
// The returned key and value are only valid for the life of the transaction.
func ( *Cursor) () ( []byte,  []byte) {
	_assert(.bucket.tx.db != nil, "tx closed")
	.stack = .stack[:0]
	,  := .bucket.pageNode(.bucket.root)
	.stack = append(.stack, elemRef{page: , node: , index: 0})
	.first()

	// If we land on an empty page then move to the next value.
	// https://github.com/boltdb/bolt/issues/450
	if .stack[len(.stack)-1].count() == 0 {
		.next()
	}

	, ,  := .keyValue()
	if ( & uint32(bucketLeafFlag)) != 0 {
		return , nil
	}
	return , 

}

// Last moves the cursor to the last item in the bucket and returns its key and value.
// If the bucket is empty then a nil key and value are returned.
// The returned key and value are only valid for the life of the transaction.
func ( *Cursor) () ( []byte,  []byte) {
	_assert(.bucket.tx.db != nil, "tx closed")
	.stack = .stack[:0]
	,  := .bucket.pageNode(.bucket.root)
	 := elemRef{page: , node: }
	.index = .count() - 1
	.stack = append(.stack, )
	.last()
	, ,  := .keyValue()
	if ( & uint32(bucketLeafFlag)) != 0 {
		return , nil
	}
	return , 
}

// Next moves the cursor to the next item in the bucket and returns its key and value.
// If the cursor is at the end of the bucket then a nil key and value are returned.
// The returned key and value are only valid for the life of the transaction.
func ( *Cursor) () ( []byte,  []byte) {
	_assert(.bucket.tx.db != nil, "tx closed")
	, ,  := .next()
	if ( & uint32(bucketLeafFlag)) != 0 {
		return , nil
	}
	return , 
}

// Prev moves the cursor to the previous item in the bucket and returns its key and value.
// If the cursor is at the beginning of the bucket then a nil key and value are returned.
// The returned key and value are only valid for the life of the transaction.
func ( *Cursor) () ( []byte,  []byte) {
	_assert(.bucket.tx.db != nil, "tx closed")

	// Attempt to move back one element until we're successful.
	// Move up the stack as we hit the beginning of each page in our stack.
	for  := len(.stack) - 1;  >= 0; -- {
		 := &.stack[]
		if .index > 0 {
			.index--
			break
		}
		.stack = .stack[:]
	}

	// If we've hit the end then return nil.
	if len(.stack) == 0 {
		return nil, nil
	}

	// Move down the stack to find the last element of the last leaf under this branch.
	.last()
	, ,  := .keyValue()
	if ( & uint32(bucketLeafFlag)) != 0 {
		return , nil
	}
	return , 
}

// Seek moves the cursor to a given key and returns it.
// If the key does not exist then the next key is used. If no keys
// follow, a nil key is returned.
// The returned key and value are only valid for the life of the transaction.
func ( *Cursor) ( []byte) ( []byte,  []byte) {
	, ,  := .seek()

	// If we ended up after the last element of a page then move to the next one.
	if  := &.stack[len(.stack)-1]; .index >= .count() {
		, ,  = .next()
	}

	if  == nil {
		return nil, nil
	} else if ( & uint32(bucketLeafFlag)) != 0 {
		return , nil
	}
	return , 
}

// Delete removes the current key/value under the cursor from the bucket.
// Delete fails if current key/value is a bucket or if the transaction is not writable.
func ( *Cursor) () error {
	if .bucket.tx.db == nil {
		return ErrTxClosed
	} else if !.bucket.Writable() {
		return ErrTxNotWritable
	}

	, ,  := .keyValue()
	// Return an error if current value is a bucket.
	if ( & bucketLeafFlag) != 0 {
		return ErrIncompatibleValue
	}
	.node().del()

	return nil
}

// seek moves the cursor to a given key and returns it.
// If the key does not exist then the next key is used.
func ( *Cursor) ( []byte) ( []byte,  []byte,  uint32) {
	_assert(.bucket.tx.db != nil, "tx closed")

	// Start from root page/node and traverse to correct page.
	.stack = .stack[:0]
	.search(, .bucket.root)

	// If this is a bucket then return a nil value.
	return .keyValue()
}

// first moves the cursor to the first leaf element under the last page in the stack.
func ( *Cursor) () {
	for {
		// Exit when we hit a leaf page.
		var  = &.stack[len(.stack)-1]
		if .isLeaf() {
			break
		}

		// Keep adding pages pointing to the first element to the stack.
		var  pgid
		if .node != nil {
			 = .node.inodes[.index].pgid
		} else {
			 = .page.branchPageElement(uint16(.index)).pgid
		}
		,  := .bucket.pageNode()
		.stack = append(.stack, elemRef{page: , node: , index: 0})
	}
}

// last moves the cursor to the last leaf element under the last page in the stack.
func ( *Cursor) () {
	for {
		// Exit when we hit a leaf page.
		 := &.stack[len(.stack)-1]
		if .isLeaf() {
			break
		}

		// Keep adding pages pointing to the last element in the stack.
		var  pgid
		if .node != nil {
			 = .node.inodes[.index].pgid
		} else {
			 = .page.branchPageElement(uint16(.index)).pgid
		}
		,  := .bucket.pageNode()

		var  = elemRef{page: , node: }
		.index = .count() - 1
		.stack = append(.stack, )
	}
}

// next moves to the next leaf element and returns the key and value.
// If the cursor is at the last leaf element then it stays there and returns nil.
func ( *Cursor) () ( []byte,  []byte,  uint32) {
	for {
		// Attempt to move over one element until we're successful.
		// Move up the stack as we hit the end of each page in our stack.
		var  int
		for  = len(.stack) - 1;  >= 0; -- {
			 := &.stack[]
			if .index < .count()-1 {
				.index++
				break
			}
		}

		// If we've hit the root page then stop and return. This will leave the
		// cursor on the last element of the last page.
		if  == -1 {
			return nil, nil, 0
		}

		// Otherwise start from where we left off in the stack and find the
		// first element of the first leaf page.
		.stack = .stack[:+1]
		.first()

		// If this is an empty page then restart and move back up the stack.
		// https://github.com/boltdb/bolt/issues/450
		if .stack[len(.stack)-1].count() == 0 {
			continue
		}

		return .keyValue()
	}
}

// search recursively performs a binary search against a given page/node until it finds a given key.
func ( *Cursor) ( []byte,  pgid) {
	,  := .bucket.pageNode()
	if  != nil && (.flags&(branchPageFlag|leafPageFlag)) == 0 {
		panic(fmt.Sprintf("invalid page type: %d: %x", .id, .flags))
	}
	 := elemRef{page: , node: }
	.stack = append(.stack, )

	// If we're on a leaf page/node then find the specific node.
	if .isLeaf() {
		.nsearch()
		return
	}

	if  != nil {
		.searchNode(, )
		return
	}
	.searchPage(, )
}

func ( *Cursor) ( []byte,  *node) {
	var  bool
	 := sort.Search(len(.inodes), func( int) bool {
		// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
		// sort.Search() finds the lowest index where f() != -1 but we need the highest index.
		 := bytes.Compare(.inodes[].key, )
		if  == 0 {
			 = true
		}
		return  != -1
	})
	if ! &&  > 0 {
		--
	}
	.stack[len(.stack)-1].index = 

	// Recursively search to the next page.
	.search(, .inodes[].pgid)
}

func ( *Cursor) ( []byte,  *page) {
	// Binary search for the correct range.
	 := .branchPageElements()

	var  bool
	 := sort.Search(int(.count), func( int) bool {
		// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
		// sort.Search() finds the lowest index where f() != -1 but we need the highest index.
		 := bytes.Compare([].key(), )
		if  == 0 {
			 = true
		}
		return  != -1
	})
	if ! &&  > 0 {
		--
	}
	.stack[len(.stack)-1].index = 

	// Recursively search to the next page.
	.search(, [].pgid)
}

// nsearch searches the leaf node on the top of the stack for a key.
func ( *Cursor) ( []byte) {
	 := &.stack[len(.stack)-1]
	,  := .page, .node

	// If we have a node then search its inodes.
	if  != nil {
		 := sort.Search(len(.inodes), func( int) bool {
			return bytes.Compare(.inodes[].key, ) != -1
		})
		.index = 
		return
	}

	// If we have a page then search its leaf elements.
	 := .leafPageElements()
	 := sort.Search(int(.count), func( int) bool {
		return bytes.Compare([].key(), ) != -1
	})
	.index = 
}

// keyValue returns the key and value of the current leaf element.
func ( *Cursor) () ([]byte, []byte, uint32) {
	 := &.stack[len(.stack)-1]

	// If the cursor is pointing to the end of page/node then return nil.
	if .count() == 0 || .index >= .count() {
		return nil, nil, 0
	}

	// Retrieve value from node.
	if .node != nil {
		 := &.node.inodes[.index]
		return .key, .value, .flags
	}

	// Or retrieve value from page.
	 := .page.leafPageElement(uint16(.index))
	return .key(), .value(), .flags
}

// node returns the node that the cursor is currently positioned on.
func ( *Cursor) () *node {
	_assert(len(.stack) > 0, "accessing a node with a zero-length cursor stack")

	// If the top of the stack is a leaf node then just return it.
	if  := &.stack[len(.stack)-1]; .node != nil && .isLeaf() {
		return .node
	}

	// Start from root and traverse down the hierarchy.
	var  = .stack[0].node
	if  == nil {
		 = .bucket.node(.stack[0].page.id, nil)
	}
	for ,  := range .stack[:len(.stack)-1] {
		_assert(!.isLeaf, "expected branch node")
		 = .childAt(.index)
	}
	_assert(.isLeaf, "expected leaf node")
	return 
}

// elemRef represents a reference to an element on a given page/node.
type elemRef struct {
	page  *page
	node  *node
	index int
}

// isLeaf returns whether the ref is pointing at a leaf page/node.
func ( *elemRef) () bool {
	if .node != nil {
		return .node.isLeaf
	}
	return (.page.flags & leafPageFlag) != 0
}

// count returns the number of inodes or page elements.
func ( *elemRef) () int {
	if .node != nil {
		return len(.node.inodes)
	}
	return int(.page.count)
}