package metrics

import (
	"time"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree"
	metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics"
)

func NewBlobovniczaTreeMetrics(path string, m metrics_impl.BlobobvnizcaMetrics) blobovniczatree.Metrics {
	return &blobovniczaTreeMetrics{
		path:    path,
		shardID: undefined,
		m:       m,
	}
}

type blobovniczaTreeMetrics struct {
	shardID string
	path    string
	m       metrics_impl.BlobobvnizcaMetrics
}

func (m *blobovniczaTreeMetrics) Blobovnicza() blobovnicza.Metrics {
	return &blobovniczaMetrics{
		shardID: func() string { return m.shardID },
		path:    m.path,
		m:       m.m,
	}
}

func (m *blobovniczaTreeMetrics) SetParentID(parentID string) {
	m.shardID = parentID
}

func (m *blobovniczaTreeMetrics) SetMode(readOnly bool) {
	m.m.SetBlobobvnizcaTreeMode(m.shardID, m.path, readOnly)
}

func (m *blobovniczaTreeMetrics) Close() {
	m.m.CloseBlobobvnizcaTree(m.shardID, m.path)
}

func (m *blobovniczaTreeMetrics) Delete(d time.Duration, success, withStorageID bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Delete", d, success, metrics_impl.NullBool{Valid: true, Bool: withStorageID})
}

func (m *blobovniczaTreeMetrics) Exists(d time.Duration, success, withStorageID bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Exists", d, success, metrics_impl.NullBool{Valid: true, Bool: withStorageID})
}

func (m *blobovniczaTreeMetrics) GetRange(d time.Duration, size int, success, withStorageID bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "GetRange", d, success, metrics_impl.NullBool{Valid: true, Bool: withStorageID})
	if success {
		m.m.AddBlobobvnizcaTreeGet(m.shardID, m.path, size)
	}
}

func (m *blobovniczaTreeMetrics) Get(d time.Duration, size int, success, withStorageID bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Get", d, success, metrics_impl.NullBool{Valid: true, Bool: withStorageID})
	if success {
		m.m.AddBlobobvnizcaTreeGet(m.shardID, m.path, size)
	}
}

func (m *blobovniczaTreeMetrics) Iterate(d time.Duration, success bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Iterate", d, success, metrics_impl.NullBool{})
}

func (m *blobovniczaTreeMetrics) Put(d time.Duration, size int, success bool) {
	m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Put", d, success, metrics_impl.NullBool{})
	if success {
		m.m.AddBlobobvnizcaTreePut(m.shardID, m.path, size)
	}
}

type blobovniczaMetrics struct {
	m       metrics_impl.BlobobvnizcaMetrics
	shardID func() string
	path    string
}

func (m *blobovniczaMetrics) AddOpenBlobovniczaSize(size uint64) {
	m.m.AddOpenBlobovniczaSize(m.shardID(), m.path, size)
}

func (m *blobovniczaMetrics) SubOpenBlobovniczaSize(size uint64) {
	m.m.SubOpenBlobovniczaSize(m.shardID(), m.path, size)
}

func (m *blobovniczaMetrics) IncOpenBlobovniczaCount() {
	m.m.IncOpenBlobovniczaCount(m.shardID(), m.path)
}

func (m *blobovniczaMetrics) DecOpenBlobovniczaCount() {
	m.m.DecOpenBlobovniczaCount(m.shardID(), m.path)
}

func (m *blobovniczaMetrics) AddOpenBlobovniczaItems(items uint64) {
	m.m.AddOpenBlobovniczaItems(m.shardID(), m.path, items)
}

func (m *blobovniczaMetrics) SubOpenBlobovniczaItems(items uint64) {
	m.m.SubOpenBlobovniczaItems(m.shardID(), m.path, items)
}