package main

import (
	"encoding/binary"
	"fmt"

	bolt "go.etcd.io/bbolt"
)

var bucketName = []byte("migrator_state")

// openStateDB opens (or creates) a BoltDB at given path.
func openStateDB(path string) (*bolt.DB, error) {
	return bolt.Open(path, 0600, nil)
}

// getLastUID returns last migrated UID for given key.
func getLastUID(db *bolt.DB, key string) (uint32, error) {
	var uid uint32
	err := db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		if b == nil {
			return nil
		}
		v := b.Get([]byte(key))
		if v == nil {
			return nil
		}
		uid = binary.BigEndian.Uint32(v)
		return nil
	})
	return uid, err
}

// setLastUID updates last migrated UID for given key.
func setLastUID(db *bolt.DB, key string, uid uint32) error {
	return db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists(bucketName)
		if err != nil {
			return err
		}
		buf := make([]byte, 4)
		binary.BigEndian.PutUint32(buf, uid)
		return b.Put([]byte(key), buf)
	})
}

// formatStateKey creates state key from src, dst and mailbox.
func formatStateKey(src, dst, mbox string) string {
	return fmt.Sprintf("%s|%s|%s", src, dst, mbox)
}
