/*
 * 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 (
	"github.com/go-chassis/go-chassis/core/lager"
	"github.com/go-chassis/go-chassis/pkg/metrics"
	"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()
	prometheusRegistry        = prometheus.NewRegistry()
	onceInit                  sync.Once
	//DefaultPrometheusSinker stores value of default prometheus exporter type
	DefaultPrometheusSinker *PrometheusMesherSinker
)

//GetSystemPrometheusRegistry return prometheus registry which mesher use
func getSystemPrometheusRegistry() *prometheus.Registry {
	return prometheusRegistry
}

func newPrometheusProvider(promRegistry prometheus.Registerer) *PrometheusMesherSinker {
	return &PrometheusMesherSinker{
		PromRegistry: promRegistry,
	}
}

func getPrometheusSinker(pr *prometheus.Registry) *PrometheusMesherSinker {
	onceInit.Do(func() {
		DefaultPrometheusSinker = newPrometheusProvider(pr)
	})
	return DefaultPrometheusSinker
}

//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)
		lager.Logger.Warnf("panics while registering metric [%s] to prometheus %s", metricName, r)
	}
}
