//
// metrics.go
// Copyright (C) 2017 kevin <kevin@ie.suberic.net>
//
// Distributed under terms of the MIT license.
//

package metrics

import (
	"log"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"gitlab.com/lyda/gqgmc/devices/geiger"
)

// Metrics collects the metrics.
type Metrics struct {
	gc geiger.Counter
	cpm,
	cps,
	volts *prometheus.HistogramVec
	errs *prometheus.GaugeVec
}

// Register metrics and metrics page.
func Register(gc geiger.Counter) *Metrics {
	var metrics = &Metrics{
		gc: gc,
		cpm: prometheus.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "gqgmc",
			Subsystem: "geiger",
			Name:      "cpm",
			Help:      "CPM readings",
			Buckets:   []float64{50, 99, 999, 1999},
		}, []string{"serial"}),
		cps: prometheus.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "gqgmc",
			Subsystem: "geiger",
			Name:      "cps",
			Help:      "CPS readings",
			Buckets:   []float64{1, 2, 16, 33},
		}, []string{"serial"}),
		volts: prometheus.NewHistogramVec(prometheus.HistogramOpts{
			Namespace: "gqgmc",
			Subsystem: "power",
			Name:      "volts",
			Help:      "Voltage readings",
			Buckets:   []float64{22, 27, 42, 50},
		}, []string{"serial"}),
		errs: prometheus.NewGaugeVec(prometheus.GaugeOpts{
			Namespace: "gqgmc",
			Subsystem: "sys",
			Name:      "errors",
			Help:      "Error counts per iteration",
		}, []string{"serial"}),
	}
	prometheus.MustRegister(metrics.cpm)
	prometheus.MustRegister(metrics.cps)
	prometheus.MustRegister(metrics.volts)
	prometheus.MustRegister(metrics.errs)

	http.Handle("/metrics", promhttp.Handler())

	return metrics
}

// Gather loop to gather metrics
func (m *Metrics) Gather(sleep int64) {
	var (
		cpm, cps uint16
		volts    int16
		err      error
	)

	for {
		errCt := 0
		if cpm, err = m.gc.GetCPM(); err != nil {
			log.Printf("gc.GetCPM error: %s\n", err)
			errCt++
		} else {
			m.cpm.WithLabelValues(m.gc.Serial()).Observe(float64(cpm))
		}
		if cps, err = m.gc.GetCPS(); err != nil {
			log.Printf("gc.GetCPS error: %s\n", err)
			errCt++
		} else {
			m.cps.WithLabelValues(m.gc.Serial()).Observe(float64(cps))
		}
		if volts, err = m.gc.Volts(); err != nil {
			log.Printf("gc.Volts error: %s\n", err)
			errCt++
		} else {
			m.volts.WithLabelValues(m.gc.Serial()).Observe(float64(volts))
		}
		m.errs.WithLabelValues(m.gc.Serial()).Set(float64(errCt))
		time.Sleep(time.Duration(sleep) * time.Second)
	}
}