// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package otelmetric

import (
	"context"

	"go.opentelemetry.io/otel/metric"

	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/gmetric"
)

// localUpDownCounterPerformer is an implementer for interface gmetric.UpDownCounterPerformer.
type localUpDownCounterPerformer struct {
	gmetric.MeterOption
	gmetric.MetricOption
	metric.Float64UpDownCounter
	constOption metric.MeasurementOption
}

// newUpDownCounterPerformer creates and returns a CounterPerformer that truly takes action to implement Counter.
func (l *localMeterPerformer) newUpDownCounterPerformer(
	meter metric.Meter,
	metricName string,
	metricOption gmetric.MetricOption,
) (gmetric.UpDownCounterPerformer, error) {
	var (
		options = []metric.Float64UpDownCounterOption{
			metric.WithDescription(metricOption.Help),
			metric.WithUnit(metricOption.Unit),
		}
	)
	counter, err := meter.Float64UpDownCounter(metricName, options...)
	if err != nil {
		return nil, gerror.WrapCodef(
			gcode.CodeInternalError,
			err,
			`create Float64Counter "%s" failed with config: %s`,
			metricName, gjson.MustEncodeString(metricOption),
		)
	}
	return &localUpDownCounterPerformer{
		MeterOption:          l.MeterOption,
		MetricOption:         metricOption,
		Float64UpDownCounter: counter,
		constOption:          genConstOptionForMetric(l.MeterOption, metricOption),
	}, nil
}

// Inc increments the counter by 1.
func (l *localUpDownCounterPerformer) Inc(ctx context.Context, option ...gmetric.Option) {
	l.Add(ctx, 1, option...)
}

// Dec decrements the counter by 1.
func (l *localUpDownCounterPerformer) Dec(ctx context.Context, option ...gmetric.Option) {
	l.Add(ctx, -1, option...)
}

// Add adds the given value to the counter.
func (l *localUpDownCounterPerformer) Add(ctx context.Context, increment float64, option ...gmetric.Option) {
	l.Float64UpDownCounter.Add(ctx, increment, generateAddOptions(l.MeterOption, l.constOption, option...)...)
}
