/*
 * 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 metrics

import (
	"fmt"
	"github.com/go-chassis/go-chassis/v2/pkg/metrics"
	"github.com/go-chassis/openlog"
	"github.com/prometheus/client_golang/prometheus"
	"runtime"
	"sync"
)

//PrometheusExporter struct has attributes for prometheus data
type PrometheusExporter struct {
	gaugesMutex   sync.RWMutex
	countersMutex sync.RWMutex
	summaryMutex  sync.RWMutex
	registry      *prometheus.Registry
	gauges        map[string]*prometheus.GaugeVec
	counters      map[string]*prometheus.CounterVec
	summary       map[string]*prometheus.SummaryVec
}

// PrometheusMesherSinker is the struct for prometheus configuration parameters
type PrometheusMesherSinker struct {
	PromRegistry prometheus.Registerer //Prometheus registry
}

var (
	//DefaultPrometheusExporter stores value of default prometheus exporter type
	DefaultPrometheusExporter = GetPrometheusExporter()
	onceInit                  sync.Once
	//DefaultPrometheusSinker stores value of default prometheus exporter type
	DefaultPrometheusSinker *PrometheusMesherSinker
)

//GetPrometheusExporter returns default prometheus exporter
func GetPrometheusExporter() *PrometheusExporter {
	//use go chassis registry
	var promRegistry = metrics.GetSystemPrometheusRegistry()
	prometheus.DefaultGatherer = promRegistry
	prometheus.DefaultRegisterer = promRegistry
	return &PrometheusExporter{
		registry:      promRegistry,
		gauges:        make(map[string]*prometheus.GaugeVec),
		counters:      make(map[string]*prometheus.CounterVec),
		summary:       make(map[string]*prometheus.SummaryVec),
		summaryMutex:  sync.RWMutex{},
		gaugesMutex:   sync.RWMutex{},
		countersMutex: sync.RWMutex{},
	}
}

//Count function returns count
func (s *PrometheusExporter) Count(name string, labelNames []string, labels prometheus.Labels) {
	s.countersMutex.RLock()
	cv, ok := s.counters[name]
	s.countersMutex.RUnlock()
	if !ok {
		cv = prometheus.NewCounterVec(prometheus.CounterOpts{
			Name: name,
			Help: name,
		}, labelNames)
		s.registry.MustRegister(cv)
		s.countersMutex.Lock()
		s.counters[name] = cv
		defer s.countersMutex.Unlock()
	}
	cv.With(labels).Add(1)

}

//Gauge function
func (s *PrometheusExporter) Gauge(name string, val float64, labelNames []string, labels prometheus.Labels) {
	defer recoverPanic(name)
	s.gaugesMutex.RLock()
	g, ok := s.gauges[name]
	s.gaugesMutex.RUnlock()
	if !ok {
		g = prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Name: name,
			Help: name,
		}, labelNames)
		s.registry.MustRegister(g)
		s.gaugesMutex.Lock()
		s.gauges[name] = g
		defer s.gaugesMutex.Unlock()
	}
	g.With(labels).Set(val)
}

//Summary function
func (s *PrometheusExporter) Summary(name string, val float64, labelNames []string, labels prometheus.Labels) {
	defer recoverPanic(name)
	s.summaryMutex.RLock()
	sm, ok := s.summary[name]
	s.summaryMutex.RUnlock()
	if !ok {
		sm = prometheus.NewSummaryVec(prometheus.SummaryOpts{
			Name: name,
			Help: name,
		}, labelNames)
		s.registry.MustRegister(sm)
		s.summaryMutex.Lock()
		s.summary[name] = sm
		defer s.summaryMutex.Unlock()
	}
	sm.With(labels).Observe(val)
}

func recoverPanic(metricName string) {
	if r := recover(); r != nil {
		pc := make([]uintptr, 10)
		runtime.Callers(1, pc)
		openlog.Warn(fmt.Sprintf("panics while registering metric [%s] to prometheus %s", metricName, r))
	}
}
