/*
* Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors

* Licensed 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 stats

import (
	"context"
	"fmt"
	"net/http"
	"time"

	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

const (
	cPrefix = "voltha"
)

type PromStatsServer struct {
	// To hold the counters which are specific to devices
	devCounters *prometheus.CounterVec
	// To hold the counters which are NOT tied to specific devices
	otherCounters *prometheus.CounterVec
	// To hold the durations which are specific to devices
	devDurations *prometheus.HistogramVec
	// To hold the durations which are NOT tied to specific to devices
	otherDurations *prometheus.HistogramVec
}

var StatsServer = PromStatsServer{}

// Start starts the statistics manager with name and makes the collected stats available
// at port p. All the statistics collected by this collector will be appended with "voltha_(name)_"
// when they appear in Prometheus. The function starts a prometheus HTTP listener in the background and does not return
// any errors, the listener is stopped on context cancellation
func (ps *PromStatsServer) Start(ctx context.Context, p int, name CollectorName) {
	//log.SetLogger(logging.New())
	ps.initializeCollectors(ctx, name)

	logger.Infow(ctx, "Starting Statistics HTTP Server", log.Fields{"listeningPort": p})

	http.Handle("/metrics", promhttp.Handler())
	server := &http.Server{Addr: fmt.Sprintf(":%d", p), Handler: nil}

	go func() {
		<-ctx.Done()
		logger.Infof(ctx, "Shutting down the Statistics HTTP server")
		err := server.Shutdown(ctx)
		if err != nil {
			logger.Errorw(ctx, "Statistics server shutting down failure", log.Fields{"error": err})
		}
	}()

	go func() {
		err := server.ListenAndServe()
		if err != nil && err != http.ErrServerClosed {
			logger.Errorw(ctx, "Starting Statistics HTTP server error", log.Fields{"error": err})
		}
	}()

	logger.Infow(ctx, "Started Prometheus listener for statistics on port", log.Fields{"port": p})
}

func (ps *PromStatsServer) initializeCollectors(ctx context.Context, name CollectorName) {
	logger.Infof(ctx, "Initializing statistics collector")

	collectorName := cPrefix + "_" + name.String()

	var (
		// in milliseconds
		defBuckets = []float64{2, 5, 10, 25, 50, 100, 300, 1000, 5000}
	)

	ps.devCounters = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: collectorName,
			Name:      "device_counters",
			Help:      "Device specific counters",
		},
		[]string{"device_id", "serial_no", "counter"},
	)

	ps.otherCounters = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: collectorName,
			Name:      "counters",
			Help:      "Non device counters",
		},
		[]string{"counter"},
	)

	ps.devDurations = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: collectorName,
			Name:      "device_durations",
			Help:      "Time taken in ms to complete a specific task for a specific device",
			Buckets:   defBuckets,
		},
		[]string{"device_id", "serial_no", "duration"},
	)

	ps.otherDurations = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: collectorName,
			Name:      "durations",
			Help:      "Time taken in ms to complete a specific task not tied to a device",
			Buckets:   defBuckets,
		},
		[]string{"duration"},
	)

	prometheus.MustRegister(ps.devCounters)
	prometheus.MustRegister(ps.otherCounters)
	prometheus.MustRegister(ps.devDurations)
	prometheus.MustRegister(ps.otherDurations)
}

// CountForDevice counts the number of times the counterName happens for device devId with serial number sn. Each call to Count increments it by one.
func (ps *PromStatsServer) CountForDevice(devId, sn string, counterName DeviceCounter) {
	if ps.devCounters != nil {
		ps.devCounters.WithLabelValues(devId, sn, counterName.String()).Inc()
	}
}

// AddForDevice adds val to counter.
func (ps *PromStatsServer) AddForDevice(devId, sn string, counter DeviceCounter, val float64) {
	if ps.devCounters != nil {
		ps.devCounters.WithLabelValues(devId, sn, counter.String()).Add(val)
	}
}

// CollectDurationForDevice calculates the duration from startTime to time.Now() for device devID with serial number sn.
func (ps *PromStatsServer) CollectDurationForDevice(devID, sn string, dName DeviceDuration, startTime time.Time) {
	if ps.otherDurations != nil {
		timeSpent := time.Since(startTime)
		ps.devDurations.WithLabelValues(devID, sn, dName.String()).Observe(float64(timeSpent.Milliseconds()))
	}
}

// Count counts the number of times the counterName happens. Each call to Count increments it by one.
func (ps *PromStatsServer) Count(counter NonDeviceCounter) {
	if ps.otherCounters != nil {
		ps.otherCounters.WithLabelValues(counter.String()).Inc()
	}
}

// Add adds val to counter.
func (ps *PromStatsServer) Add(counter NonDeviceCounter, val float64) {
	if ps.otherCounters != nil {
		ps.otherCounters.WithLabelValues(counter.String()).Add(val)
	}
}

// CollectDuration calculates the duration from startTime to time.Now().
func (ps *PromStatsServer) CollectDuration(dName NonDeviceDuration, startTime time.Time) {
	if ps.otherDurations != nil {
		timeSpent := time.Since(startTime)
		ps.otherDurations.WithLabelValues(dName.String()).Observe(float64(timeSpent.Milliseconds()))
	}
}
