package blobovniczatree

import (
	"context"

	"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
	"go.uber.org/zap"
)

// Open opens blobovnicza tree.
func (b *Blobovniczas) Open(readOnly bool) error {
	b.readOnly = readOnly
	b.metrics.SetMode(readOnly)
	b.openManagers()
	return nil
}

// Init initializes blobovnicza tree.
//
// Should be called exactly once.
func (b *Blobovniczas) Init() error {
	b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas)

	if b.readOnly {
		b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization)
		return nil
	}

	return b.iterateLeaves(context.TODO(), func(p string) (bool, error) {
		shBlz := b.getBlobovniczaWithoutCaching(p)
		_, err := shBlz.Open()
		if err != nil {
			return true, err
		}
		defer shBlz.Close()

		b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p))
		return false, nil
	})
}

func (b *Blobovniczas) openManagers() {
	b.commondbManager.Open() // order important
	b.activeDBManager.Open()
	b.dbCache.Open()
}

// Close implements common.Storage.
func (b *Blobovniczas) Close() error {
	b.dbCache.Close() // order important
	b.activeDBManager.Close()
	b.commondbManager.Close()

	return nil
}

// returns blobovnicza with path p
//
// If blobovnicza is already cached, instance from cache is returned w/o changes.
func (b *Blobovniczas) getBlobovnicza(p string) *sharedDB {
	return b.dbCache.GetOrCreate(p)
}

func (b *Blobovniczas) getBlobovniczaWithoutCaching(p string) *sharedDB {
	return b.commondbManager.GetByPath(p)
}