/*
 * Copyright 2018-present Open Networking Foundation

 * 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()))
	}
}
