/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package prometheus

import (
	"context"
	"strconv"
	"strings"
	"sync"
	"time"
)
import (
	"github.com/prometheus/client_golang/prometheus"
)

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
	"github.com/apache/dubbo-go/common/extension"
	"github.com/apache/dubbo-go/common/logger"
	"github.com/apache/dubbo-go/config"
	"github.com/apache/dubbo-go/metrics"
	"github.com/apache/dubbo-go/protocol"
)

const (
	reporterName = "prometheus"
	serviceKey   = constant.SERVICE_KEY
	groupKey     = constant.GROUP_KEY
	versionKey   = constant.VERSION_KEY
	methodKey    = constant.METHOD_KEY
	timeoutKey   = constant.TIMEOUT_KEY

	providerKey = "provider"
	consumerKey = "consumer"

	// to identify the metric's type
	histogramSuffix = "_histogram"
	// to identify the metric's type
	summarySuffix = "_summary"
)

var (
	labelNames       = []string{serviceKey, groupKey, versionKey, methodKey, timeoutKey}
	namespace        = config.GetApplicationConfig().Name
	reporterInstance *PrometheusReporter
	reporterInitOnce sync.Once
)

// should initialize after loading configuration
func init() {

	extension.SetMetricReporter(reporterName, newPrometheusReporter)
}

// PrometheusReporter will collect the data for Prometheus
// if you want to use this feature, you need to initialize your prometheus.
// https://prometheus.io/docs/guides/go-application/
type PrometheusReporter struct {

	// report the consumer-side's summary data
	consumerSummaryVec *prometheus.SummaryVec
	// report the provider-side's summary data
	providerSummaryVec *prometheus.SummaryVec

	// report the provider-side's histogram data
	providerHistogramVec *prometheus.HistogramVec
	// report the consumer-side's histogram data
	consumerHistogramVec *prometheus.HistogramVec
}

// Report reports the duration to Prometheus
// the role in url must be consumer or provider
// or it will be ignored
func (reporter *PrometheusReporter) Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
	url := invoker.GetUrl()
	var sumVec *prometheus.SummaryVec
	var hisVec *prometheus.HistogramVec
	if isProvider(url) {
		sumVec = reporter.providerSummaryVec
		hisVec = reporter.providerHistogramVec
	} else if isConsumer(url) {
		sumVec = reporter.consumerSummaryVec
		hisVec = reporter.consumerHistogramVec
	} else {
		logger.Warnf("The url belongs neither the consumer nor the provider, "+
			"so the invocation will be ignored. url: %s", url.String())
		return
	}

	labels := prometheus.Labels{
		serviceKey: url.Service(),
		groupKey:   url.GetParam(groupKey, ""),
		versionKey: url.GetParam(versionKey, ""),
		methodKey:  invocation.MethodName(),
		timeoutKey: url.GetParam(timeoutKey, ""),
	}

	costMs := float64(cost.Nanoseconds() / constant.MsToNanoRate)
	sumVec.With(labels).Observe(costMs)
	hisVec.With(labels).Observe(costMs)
}

func newHistogramVec(side string) *prometheus.HistogramVec {
	mc := config.GetMetricConfig()
	return prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: namespace,
			Subsystem: side,
			Name:      serviceKey + histogramSuffix,
			Help:      "This is the dubbo's histogram metrics",
			Buckets:   mc.GetHistogramBucket(),
		},
		labelNames)
}

// whether this url represents the application received the request as server
func isProvider(url common.URL) bool {
	role := url.GetParam(constant.ROLE_KEY, "")
	return strings.EqualFold(role, strconv.Itoa(common.PROVIDER))
}

// whether this url represents the application sent then request as client
func isConsumer(url common.URL) bool {
	role := url.GetParam(constant.ROLE_KEY, "")
	return strings.EqualFold(role, strconv.Itoa(common.CONSUMER))
}

// newSummaryVec create SummaryVec, the Namespace is dubbo
// the objectives is from my experience.
func newSummaryVec(side string) *prometheus.SummaryVec {
	return prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Namespace: namespace,
			Help:      "This is the dubbo's summary metrics",
			Subsystem: side,
			Name:      serviceKey + summarySuffix,
			Objectives: map[float64]float64{
				0.5:   0.01,
				0.75:  0.01,
				0.90:  0.005,
				0.98:  0.002,
				0.99:  0.001,
				0.999: 0.0001,
			},
		},
		labelNames,
	)
}

// newPrometheusReporter create new prometheusReporter
// it will register the metrics into prometheus
func newPrometheusReporter() metrics.Reporter {
	if reporterInstance == nil {
		reporterInitOnce.Do(func() {
			reporterInstance = &PrometheusReporter{
				consumerSummaryVec: newSummaryVec(consumerKey),
				providerSummaryVec: newSummaryVec(providerKey),

				consumerHistogramVec: newHistogramVec(consumerKey),
				providerHistogramVec: newHistogramVec(providerKey),
			}
			prometheus.MustRegister(reporterInstance.consumerSummaryVec, reporterInstance.providerSummaryVec,
				reporterInstance.consumerHistogramVec, reporterInstance.providerHistogramVec)
		})
	}
	return reporterInstance
}
