package store

import (
	
	

	bolt 
)

func () {
	initDB["initialize command history table"] = func( *bolt.Tx) error {
		,  := .CreateBucketIfNotExists([]byte(bucketCmd))
		return 
	}
}

// NextCmdSeq returns the next sequence number of the command history.
func ( *dbStore) () (int, error) {
	var  uint64
	 := .db.View(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		 = .Sequence() + 1
		return nil
	})
	return int(), 
}

// AddCmd adds a new command to the command history.
func ( *dbStore) ( string) (int, error) {
	var (
		 uint64
		 error
	)
	 = .db.Update(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		,  = .NextSequence()
		if  != nil {
			return 
		}
		return .Put(marshalSeq(), []byte())
	})
	return int(), 
}

// DelCmd deletes a command history item with the given sequence number.
func ( *dbStore) ( int) error {
	return .db.Update(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		return .Delete(marshalSeq(uint64()))
	})
}

// Cmd queries the command history item with the specified sequence number.
func ( *dbStore) ( int) (string, error) {
	var  string
	 := .db.View(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		 := .Get(marshalSeq(uint64()))
		if  == nil {
			return ErrNoMatchingCmd
		}
		 = string()
		return nil
	})
	return , 
}

// IterateCmds iterates all the commands in the specified range, and calls the
// callback with the content of each command sequentially.
func ( *dbStore) (,  int,  func(Cmd)) error {
	return .db.View(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		 := .Cursor()
		for ,  := .Seek(marshalSeq(uint64()));  != nil && unmarshalSeq() < uint64(); ,  = .Next() {
			(Cmd{Text: string(), Seq: int(unmarshalSeq())})
		}
		return nil
	})
}

// Cmds returns the contents of all commands within the specified range.
//
// NOTE: Deprecated as of 0.13. Delete after release of 0.14.
func ( *dbStore) (,  int) ([]string, error) {
	var  []string
	 := .IterateCmds(, , func( Cmd) {
		 = append(, .Text)
	})
	return , 
}

// CmdsWithSeq returns all commands within the specified range.
func ( *dbStore) (,  int) ([]Cmd, error) {
	var  []Cmd
	 := .IterateCmds(, , func( Cmd) {
		 = append(, )
	})
	return , 
}

// NextCmd finds the first command after the given sequence number (inclusive)
// with the given prefix.
func ( *dbStore) ( int,  string) (Cmd, error) {
	var  Cmd
	 := .db.View(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		 := .Cursor()
		 := []byte()
		for ,  := .Seek(marshalSeq(uint64()));  != nil; ,  = .Next() {
			if bytes.HasPrefix(, ) {
				 = Cmd{Text: string(), Seq: int(unmarshalSeq())}
				return nil
			}
		}
		return ErrNoMatchingCmd
	})
	return , 
}

// PrevCmd finds the last command before the given sequence number (exclusive)
// with the given prefix.
func ( *dbStore) ( int,  string) (Cmd, error) {
	var  Cmd
	 := .db.View(func( *bolt.Tx) error {
		 := .Bucket([]byte(bucketCmd))
		 := .Cursor()
		 := []byte()

		var  []byte
		,  := .Seek(marshalSeq(uint64()))
		if  == nil { // upto > LAST
			,  = .Last()
			if  == nil {
				return ErrNoMatchingCmd
			}
		} else {
			,  = .Prev() // upto exists, find the previous one
		}

		for ;  != nil; ,  = .Prev() {
			if bytes.HasPrefix(, ) {
				 = Cmd{Text: string(), Seq: int(unmarshalSeq())}
				return nil
			}
		}
		return ErrNoMatchingCmd
	})
	return , 
}

func ( uint64) []byte {
	 := make([]byte, 8)
	binary.BigEndian.PutUint64(, )
	return 
}

func ( []byte) uint64 {
	return binary.BigEndian.Uint64()
}